<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7224548894465589501</id><updated>2012-02-11T13:16:09.362-06:00</updated><category term='mobile'/><category term='android'/><category term='accessibility'/><category term='iPhone'/><category term='css'/><category term='agile'/><category term='java'/><category term='books'/><category term='patterns'/><category term='spring'/><category term='security'/><category term='mac'/><category term='Objective-C'/><category term='jQuery Mobile'/><category term='JavaScript'/><category term='web services'/><category term='conferences'/><category term='database'/><title type='text'>People are the platform</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-7186441123021264053</id><published>2011-12-10T12:50:00.003-06:00</published><updated>2011-12-10T13:12:03.557-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery Mobile'/><title type='text'>jQuery Mobile Events Diagram</title><content type='html'>When building jQuery Mobile applications I often find it useful to have a quick reference to all events within the lifecycle.  This jQuery Mobile events diagram should be helpful for new developers learning the jQuery Mobile event model or advanced developers that often bind to these events:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://3.bp.blogspot.com/-6ypdAEZkLnM/TuOqsQXsBBI/AAAAAAAAAKM/Uppk_v-Bqmk/s1600/fig1-jqm-page-eventsF.png" border="0" alt="jQuery Mobile Events Diagram" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This diagram is also available within &lt;a href="http://www.amazon.com/Pro-jQuery-Mobile-Brad-Broulik/dp/1430239662/ref=sr_1_9?s=books&amp;ie=UTF8&amp;qid=1320859255&amp;sr=1-9" target="new"&gt;Pro jQuery Mobile&lt;/a&gt;.  In addition to the diagram, you will also find detailed examples and descriptions for each event.  Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-7186441123021264053?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/7186441123021264053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2011/12/jquery-mobile-events-diagram.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/7186441123021264053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/7186441123021264053'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2011/12/jquery-mobile-events-diagram.html' title='jQuery Mobile Events Diagram'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-6ypdAEZkLnM/TuOqsQXsBBI/AAAAAAAAAKM/Uppk_v-Bqmk/s72-c/fig1-jqm-page-eventsF.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-3707231899539996756</id><published>2011-05-21T13:26:00.002-05:00</published><updated>2011-05-21T13:29:41.802-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><title type='text'>Titanium MVC Pattern</title><content type='html'>Are you looking to simplify your Titanium programming model?  Leveraging the MVC pattern will help produce cleaner code and promote reusability.  Applying the MVC pattern within Titanium is relatively easy and it provides all the advantages we expect from MVC.  Here is a quick example of the view and controller components:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;View&lt;/h3&gt;The &lt;em&gt;view&lt;/em&gt; is responsible for creating the window and adding the necessary UI components.  Your views may optionally manage styling properties (color, font, and positioning).  Ideally, the better practice is to extract all styling properties into external JSS files but I found this feature to be too quirky in its initial release.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span class="code-highlight1"&gt;&lt;br /&gt;/**&lt;br /&gt; * View Template&lt;br /&gt; * Usage: &lt;em&gt;APP.ui.LoginView.createWindow();&lt;/em&gt;&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;APP.ui.LoginView = (&lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;()&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="code-highlight1"&gt;/* private methods to build UI specific components */&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt; buildWindow()&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;return&lt;/span&gt; Ti.UI.createWindow(&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;             title: &lt;span style="color: rgb(51, 102, 204);"&gt;'Title'&lt;/span&gt;,&lt;br /&gt;             barColor: &lt;span style="color: rgb(51, 102, 204);"&gt;'#225377'&lt;/span&gt;,&lt;br /&gt;             backgroundColor: &lt;span style="color: rgb(51, 102, 204);"&gt;'#d4d2d3'&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt; buildUsernameTextField(win)&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;        win.usernameTextField = Ti.UI.createTextField(&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;            autocorrect: &lt;span style="color: rgb(51, 102, 204);"&gt;false&lt;/span&gt;,&lt;br /&gt;            hintText: &lt;span style="color: rgb(51, 102, 204);"&gt;'Username'&lt;/span&gt;,&lt;br /&gt;            left: &lt;span style="color: rgb(51, 102, 204);"&gt;10&lt;/span&gt;,&lt;br /&gt;            width: &lt;span style="color: rgb(51, 102, 204);"&gt;285&lt;/span&gt;,&lt;br /&gt;            suppressReturn:&lt;span style="color: rgb(51, 102, 204);"&gt;false&lt;/span&gt;,&lt;br /&gt;            autocapitalization: Ti.UI.TEXT_AUTOCAPITALIZATION_NONE,&lt;br /&gt;            clearButtonMode: Ti.UI.INPUT_BUTTONMODE_ONFOCUS,&lt;br /&gt;            borderStyle: Ti.UI.INPUT_BORDERSTYLE_NONE,&lt;br /&gt;            returnKeyType: Ti.UI.RETURNKEY_NEXT&lt;br /&gt;        &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;);&lt;br /&gt;     &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     &lt;span class="code-highlight1"&gt;/* Public API only exposes the createWindow method. */&lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;         createWindow: &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;()&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;             &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;var&lt;/span&gt; win = buildWindow();&lt;br /&gt;             buildUsernameTextField(win);&lt;br /&gt;             &lt;span class="code-highlight1"&gt;//buildComponentX(win);&lt;/span&gt;&lt;br /&gt;             &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;return&lt;/span&gt; win;&lt;br /&gt;         &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;)();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Controller&lt;/h3&gt;The &lt;em&gt;controller&lt;/em&gt; is responsible for managing events (button taps) and navigation.  Events handlers communicate with server-side services when necessary.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span class="code-highlight1"&gt;/**&lt;br /&gt; * Controller Template&lt;br /&gt; * Usage: &lt;em&gt;APP.ui.LoginController.init();&lt;/em&gt;&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;APP.ui.LoginController = (function()&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     &lt;span class="code-highlight1"&gt;/* Private helper methods */&lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt; setEventListeners(win)&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;         win.usernameTextField.addEventListener('return', &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;()&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;             win.passwordTextField.focus();&lt;br /&gt;         &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;);&lt;br /&gt;        &lt;br /&gt;         win.passwordTextField.addEventListener('return', &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;()&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;            handleLoginEvent(win);&lt;br /&gt;         &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;);&lt;br /&gt;     &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     &lt;span class="code-highlight1"&gt;/* Public API only exposes init method. */&lt;/span&gt;  &lt;br /&gt;     &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;         init: &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;()&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;{&lt;/span&gt;&lt;br /&gt;             &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;var&lt;/span&gt; win = APP.ui.LoginView.createWindow();&lt;br /&gt;             setEventListeners(win);&lt;br /&gt;             win.open();&lt;br /&gt;         &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;;&lt;br /&gt;&lt;span style="color: rgb(0, 136, 0); font-weight: bold;"&gt;}&lt;/span&gt;)();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Model&lt;/h3&gt;The model is typically a JSON payload retrieved from a Restful service. For example, the &lt;em&gt;handleLoginEvent&lt;/em&gt; will return user profile information after a successful login.  We can save this object locally and leverage it on subsequent screens.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Advantages:&lt;ul&gt;&lt;li&gt;Small objects and methods.&lt;/li&gt;&lt;li&gt;Improved organization and readability&lt;/li&gt;&lt;li&gt;Promotes reusability of views.  Also, the decoupled views allow you to swap in native-specific UIs when necessary all while reusing a single controller.&lt;/li&gt;&lt;li&gt;Simpler maintenance.&lt;/li&gt;&lt;li&gt;Allows for simpler unit testing with responsibilities split into separate objects.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I expect many developers may fall in the trap of modeling their JavaScript according to the &lt;a href="http://developer.appcelerator.com/doc/kitchensink" target="new"&gt;KitchenSink&lt;/a&gt; examples.  While those examples are useful, their programming practices should not be followed for a production ready app.  For example, their examples do not leverage closure to eliminate global scope, they do not use a namespace convention for improved organization, and all MVC responsibilities were bundled within a single object.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-3707231899539996756?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/3707231899539996756/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2011/03/titanium-mvc-pattern.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3707231899539996756'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3707231899539996756'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2011/03/titanium-mvc-pattern.html' title='Titanium MVC Pattern'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-1549313899635757394</id><published>2011-03-20T09:04:00.000-05:00</published><updated>2011-03-20T09:04:25.559-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><category scheme='http://www.blogger.com/atom/ns#' term='conferences'/><title type='text'>Mobile March</title><content type='html'>The &lt;a href="http://mobilemarchtc.com/" target="new"&gt;Mobile March&lt;/a&gt; conference was held at the Best Buy headquarters this weekend. Here is a brief recap of the sessions I attended:&lt;br /&gt;&lt;br /&gt;﻿﻿﻿﻿﻿&lt;img width="650" src="http://3.bp.blogspot.com/-DwQTzH5xC3Q/TYVLW2M4-iI/AAAAAAAAAIU/msrk_6jKdqk/s1600/sessions-am.png" alt="Morning Sessions" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Keynote&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;There is a low tolerance for mediocrity in mobile.  Apps have a 50% abandon rate after the first 30 days.&lt;/li&gt;&lt;li&gt;Mobile trends: News via tablets, social media, location based apps, group messaging with apps like &lt;a href="http://belugapods.com/" target="new"&gt;Beluga&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Mobile marketing, what's working: Incentives, deals, hot buys, and rebates.&lt;/li&gt;&lt;li&gt;5 things to consider: Activate advertising with text or QR codes, activate sponsorships with mobile, launch mobile coupons, test a location based campaign, use mobile to drive app downloads.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;Simple and low cost mobile technologies have proven to be very effective solutions.  SMS, QR codes, and social media fall within this category.  The goal is simple, get customers to engage and then extend the conversation.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Cracking the Code: QR Codes and Coupons&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;QR code scanning is up 1000% in the last 6 months.  Consumers love to scan QR barcodes.&lt;/li&gt;&lt;li&gt;QR codes link users to additional information.  For example, Best Buy has QR codes next to each price tag. Launching the QR code provides the user with detailed information and user reviews.  Additionally, if you scan another product you can see a side-by-side comparison of both products.&lt;/li&gt;&lt;li&gt;Looking for a QR reader?  Try &lt;a href="http://itunes.apple.com/us/app/neoreader/id284973754?mt=8" target="new"&gt;NeoReader&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://blogs.citypages.com/food/2011/01/chino_latinos_s.php" target="new"&gt;Chino Latino&lt;/a&gt; is the first restaurant to put a QR code on a billboard.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;Mobile March had QR codes at the entrance of each session.  Scanning the code displayed the presenters bio.  Again, this is a simple, low cost solution to interact with mobile customers.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The iPhone vs Android Showdown&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;iPhone&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://developer.apple.com/xcode/" target="new"&gt;Xcode 4&lt;/a&gt;, which was released a few weeks ago, has finally simplified the organization of their Interface Builder and code editor.  Navigating between Interface Builder and code is much quicker via their new tab orientation instead of externalized windows found in Xcode 3.&lt;/li&gt;&lt;li&gt;Xcode is the superior IDE when compared to Android development on Eclipse.  The Interface Builder is far superior and the iPhone emulator loads much faster.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Android&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Android's distribution model is superior.  It takes several hours to deploy to Android's Market.  The Apple Store certification process may take up to 2 weeks.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;Creating a mobile wireframe is easily 2-3 times faster in Xcode.  While Android finally released a UI builder with their 3.0 SDK it is far from perfect.  A major Android advantage is their time to market on app upgrades.  If you have a production defect will you have the patience to wait for the Apple certification process?&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Grill yourself&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Think about UX as soon as you have an idea.&lt;/li&gt;&lt;li&gt;Keep apps simple and moving parts to a minimum.&lt;/li&gt;&lt;li&gt;You can sell anything if you can do it simple, quick, and cheap.&lt;/li&gt;&lt;li&gt;Share the analytics about your mobile users with your organization.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;﻿﻿﻿﻿﻿&lt;img width="650" src="http://4.bp.blogspot.com/-VdQLBoYEf6E/TYVNH9URZ0I/AAAAAAAAAIk/l6hYYZko188/s1600/sessions-pm.png" alt="Afternoon Sessions" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Current State of the Mobile Web&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Native advantages: performance, consistency, safety, convenience, functionality.&lt;/li&gt;&lt;li&gt;Native disadvantages: harder to build, approval process, hard to discover, fragmentation.&lt;/li&gt;&lt;li&gt;Mobile Web advantages: open, connected, ubiquitous, unregulated.&lt;/li&gt;&lt;li&gt;Mobile Web disadvantages: unregulated, performance is slower.&lt;/li&gt;&lt;li&gt;Mozilla and Google are coming out with web app stores soon.&lt;/li&gt;&lt;li&gt;Looking for a fixed header and footer for your scrollable window on iOS?  Try &lt;a href="http://cubiq.org/iscroll" target="new"&gt;iScroll&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;There are clearly many advantages to Mobile Web.  Its deployment model is instantaneous and it helps reduce fragmentation and development costs.  If you are interested in jQuery Mobile, here is a good &lt;a href="http://www.meetup.com/bostonphp/pages/Video_and_Resources_for_jQuery_Mobile/" target="new"&gt;presentation&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Blackberry Playbook&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Cost of entry&lt;/li&gt;&lt;ul&gt;&lt;li&gt;BlackBerry: Free&lt;/li&gt;&lt;li&gt;Android: $25 (one time)&lt;/li&gt;&lt;li&gt;Apple: $99/yr&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Distribution&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Google: lass than hour&lt;/li&gt;&lt;li&gt;BlackBerry: 4-6 hours&lt;/li&gt;&lt;li&gt;Apple: up to 2 weeks&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;BlackBerry has a "try before you buy" program in their AppWorld store which is unique.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;The Playbook tablet by BlackBerry will be released soon.  While competition is good, they definitely have an uphill battle to climb.&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-1549313899635757394?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/1549313899635757394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2011/03/mobile-march.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1549313899635757394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1549313899635757394'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2011/03/mobile-march.html' title='Mobile March'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-DwQTzH5xC3Q/TYVLW2M4-iI/AAAAAAAAAIU/msrk_6jKdqk/s72-c/sessions-am.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-8899053640258906289</id><published>2011-03-06T07:34:00.008-06:00</published><updated>2011-03-07T21:36:19.948-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conferences'/><title type='text'>No Fluff Just Stuff: Minneapolis Summary (Spring)</title><content type='html'>The &lt;a href="http://www.nofluffjuststuff.com/home/main" target="new"&gt;No Fluff Just Stuff&lt;/a&gt; conference was back in Minneapolis. Here is a brief recap of the sessions I attended:&lt;br /&gt;&lt;br /&gt;﻿﻿﻿﻿﻿&lt;img width="650" src="http://1.bp.blogspot.com/-Z0EiQWPEdL4/TXGtWmbTkYI/AAAAAAAAAH8/gOhAmBPc6JY/s1600/friday.jpg" alt="Friday Sessions" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;NoSQL Smackdown!&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;NoSQL is a set of different approaches to storing and retrieving data&lt;/li&gt;&lt;li&gt;Cassandra:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Implementation Language: Java 6&lt;/li&gt;&lt;li&gt;Data Model: BigTable&lt;/li&gt;&lt;li&gt;Advantages: Highly scaleable&lt;/li&gt;&lt;li&gt;Deployments: facebook, twitter&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;MongoDB:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Implementation Language: C++&lt;/li&gt;&lt;li&gt;Data Model: JSON&lt;/li&gt;&lt;li&gt;Advantages: Simple&lt;/li&gt;&lt;li&gt;Deployments: sourceforge, bit.ly, shutterfly, Etsy&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;I like the fact MongoDB persists JSON.  I implemented a similar solution on a recent mobile application where JSON objects were persisted on the client database.  This solution is simple, requires minimal code, and provides great flexibility.  If the domain model changes the database requires ZERO changes!&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Pragmatic Architecture&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Architects will be much more effective if they have a solid understanding of the business domain.&lt;/li&gt;&lt;li&gt;A good architecture makes it easy for developers to make "right" decisions.&lt;/li&gt;&lt;li&gt;Avoid architectures that were designed with Resume Driven Design (RDD).&lt;/li&gt;&lt;li&gt;Architects must be familiar with all technologies.&lt;/li&gt;&lt;li&gt;Prefer full-time architects or architects that at least see the consequences of their design after deploying to production.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;Over the past twelve years I have observed that the most effective architects code at least 49%.  The more the better.  If this isn't the case they simply won't be effective long term.  The best architects produce working code in addition to their design artifacts.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Introducing Spring Roo: From Zero to Working Spring Application in Record Time&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;The rapid scaffolding is intriguing.&lt;/li&gt;&lt;li&gt;The de-Rooing is convenient when you need to remove the Roo footprint.&lt;/li&gt;&lt;li&gt;I particularly like the ability to replay your commands for project setup.  Extract the Roo scripts and replaying them for the next project can offer rapid productivity.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;Roo makes sense for rapid prototyping or if you need to build an application in &lt;a href="http://bradbroulik.blogspot.com/2011/02/agile-strategy-for-24-hour-coders.html" target="new"&gt;24-hours&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img width="650" src="http://4.bp.blogspot.com/-ZFd7h6vU0R8/TXI5X_JcymI/AAAAAAAAAIE/qWajPwI-lnU/s1600/saturday.jpg" alt="Saturday sessions" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;HTML5: The JavaScript Parts&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Prefer &lt;em&gt;document.querySelector()&lt;/em&gt; over &lt;em&gt;document.getElementById()&lt;/em&gt; for much improved performance gains.&lt;/li&gt;&lt;li&gt;By default, &lt;em&gt;navigator.geolocation&lt;/em&gt; is not enabled in Chrome.  The user must explicitly enable it.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.modernizr.com/" target="new"&gt;Modernizr&lt;/a&gt; can help with progressive enhancement by detecting browser feature availability and reacting appropriately.&lt;/li&gt;&lt;li&gt;Web Workers are not supported on mobile browsers:(&lt;/li&gt;&lt;li&gt;&lt;a href="http://caniuse.com/" target="new"&gt;When can I use...&lt;/a&gt; shows feature compatibility by browser.&lt;/li&gt;&lt;li&gt;&lt;a href="http://fmbip.com" target="new"&gt;findmebyIP&lt;/a&gt; shows feature support for your current browser.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;I predict a strong enterprise push for mobile web development starting this year.  Mobile Web is device agnostic and jQuery Mobile will simplify the adoption.  Even facebook has admitted to the pain, duplication, and cost of supporting five separate native apps.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Developing Social-Ready Web Applications&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Enable twitter integration with &lt;a href="http://dev.twitter.com/anywhere" target="new"&gt;@Anywhere&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Dynamically search for tweets from twitter's restful API: &lt;em&gt;http://search.twitter.com/search.json?q=nfjs&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Dynamically find the friends of a twitter user: &lt;em&gt;http://api.twitter.com/1/friends/ids.json?screen_name=&amp;lt;username&amp;gt;&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Enable facebook integration with their &lt;a href="http://developers.facebook.com/docs/plugins/" target="new"&gt;Social Plugins&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Dynamically retrieve the user info for a facebook user: &lt;em&gt;https://graph.facebook.com/&amp;lt;username&amp;gt;&lt;/em&gt;&lt;/li&gt;&lt;li&gt;LinkedIn's developer &lt;a href="http://developer.linkedin.com/community/widgets" target="new"&gt;widgets&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;The greatest benefit of &lt;a href="http://www.springsource.org/spring-social" target="new"&gt;Spring Social&lt;/a&gt; is its simplification of SSO integration.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Git Going with Distributed Version Control&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Git is 10-100 times faster than Subversion.&lt;/li&gt;&lt;li&gt;Git can bisect bugs or find the commit that broke a test.&lt;/li&gt;&lt;li&gt;Git can search (grep) the entire revision history without checkouts.  For example, I can find a particular commit where a line was added.&lt;/li&gt;&lt;li&gt;Git persists the versioned artifacts to the file system as 40 character hashes.  This approach is very lightweight and provides extremely fast compares.&lt;/li&gt;&lt;li&gt;Unlike Subversion, Git &lt;em&gt;does not&lt;/em&gt; pollute the source directories with version control meta data.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;I have been working with Git for several weeks.  Matthew's &lt;a href="http://refcardz.dzone.com/refcardz/getting-started-git" target="new"&gt;DZone Refcard&lt;/a&gt; about Git has also been a very valuable resource.  Git was my favorite session so far!&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img width="650" src="http://3.bp.blogspot.com/-p4jryfs5ZdI/TXLeyeqt_uI/AAAAAAAAAIM/n-Odji31g48/s1600/sunday.jpg" alt="Sunday sessions" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;jQuery: Ajax Made Easy&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;jQuery has a small footprint, the code is clean, it has good documentation, has excellent CSS selector support, and it's the most popular.&lt;/li&gt;&lt;li&gt;If you only need the CSS selector support it's available in &lt;a href="http://sizzlejs.com/" target="new"&gt;Sizzle&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;If you want read well written JavaScript it is worth your time to checkout &lt;a href="https://github.com/jquery/jquery" target="new"&gt;jQuery's source code.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Going Mobile with jQuery&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;50% of population will have smartphone by the end of 2011&lt;/li&gt;&lt;li&gt;&lt;a hef="http://jeromeetienne.github.com/jquery-mobile-960/" target="new"&gt;Tablet support&lt;/a&gt; is now available&lt;/li&gt;&lt;li&gt;Favorite quote: "Using an iPhone during a meeting makes you look like a proactive employee." --Nathaniel Schutta&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;I have been working with jQuery Mobile for several months now and it is a simple framework.  The team is extremely eager to support nearly every device.  After spending time learning Git, I am finally setup to help contribute to the project.  Now I need to find the time to focus on a task, defect, or test!  In addition to &lt;a href="http://jquerymobile.com/" target="new"&gt;jQuery Mobile&lt;/a&gt; there are also mobile web frameworks available from &lt;a href="http://www.yuiblog.com/blog/2010/09/07/yui-3-2-0/" target="new"&gt;YUI&lt;/a&gt;, &lt;a href="http://www.jqtouch.com/" target="new"&gt;jQTouch&lt;/a&gt;, and &lt;a href="http://joapp.com/" target="new"&gt;Jo&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Code Craft&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;We need to spend more time reading code.&lt;/li&gt;&lt;li&gt;There is nothing wrong with simplicity!  Simple code == good&lt;/li&gt;&lt;li&gt;If you are having difficulties with code reviews try &lt;a href="http://www.atlassian.com/software/crucible/" target="new"&gt;Crucible&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mobile GUI Frameworks&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.jqtouch.com/" target="new"&gt;jQTouch&lt;/a&gt; is the smoothest mobile web framework on the market today.  However, only iOS is able to reap many of these benefits.&lt;/li&gt;&lt;li&gt;&lt;a href="http://joapp.com/" target="new"&gt;Jo&lt;/a&gt; is a new mobile framework I definitely want to look at closer.  It's lighter weight than &lt;a href="http://jquerymobile.com/" target="new"&gt;jQuery Mobile&lt;/a&gt; and the end user codes primarily in JavaScript whereas jQuery Mobile is more markup driven.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-8899053640258906289?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/8899053640258906289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2011/03/no-fluff-just-stuff-minneapolis-summary.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/8899053640258906289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/8899053640258906289'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2011/03/no-fluff-just-stuff-minneapolis-summary.html' title='No Fluff Just Stuff: Minneapolis Summary (Spring)'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-Z0EiQWPEdL4/TXGtWmbTkYI/AAAAAAAAAH8/gOhAmBPc6JY/s72-c/friday.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-192554129985119841</id><published>2011-02-14T17:24:00.004-06:00</published><updated>2011-02-14T17:32:22.779-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Agile Strategy for 24-hour Coders Challenge</title><content type='html'>&lt;img style="border:0px; float:right; margin:-20px 0px -5px 10px; width: 135px; height:&lt;br /&gt;135px;" src="http://4.bp.blogspot.com/-Ca53h6Q6ecU/TVNO8zsXnzI/AAAAAAAAAHc/FkL1jAnswNQ/s400/R_C_Wall_Clock.jpg" border="0" alt="clock" id="BLOGGER_PHOTO_ID_5571883970562858802" /&gt;&lt;p&gt;Can we build an app in twenty-four hours?  We definitely can with the right planning and tools.  The &lt;a href="http://nerdery.com/" target="new"&gt;Nerdery&lt;/a&gt; is organizing an &lt;a href="http://tc2011.overnightwebsitechallenge.com/" target="new"&gt;overnight website challenge&lt;/a&gt; in the Twin Cities where teams compete to build the best Web application within twenty-four hours.  I have always watched these &lt;a href="http://en.wikipedia.org/wiki/Food_Network_Challenge" target="new"&gt;competitions&lt;/a&gt; on TV but never with software developers!  What is the ideal strategy for this competition?&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Agile Planning Strategy&lt;/h3&gt;&lt;p&gt;Pre-competition planning is the most important step to success.  Literally, every detail must be planned prior to competition.  This will yield great efficiencies during the competition.  Pre-competition planning considerations must include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Technology stack: Java, Grails, Rails, PHP&lt;/li&gt;&lt;li&gt;Tool suite: IDE, graphic editors&lt;/li&gt;&lt;li&gt;Source repository: GIT, shared local repository&lt;/li&gt;&lt;li&gt;Hosting platform: &lt;a href="http://code.google.com/appengine/" target="new"&gt;Google App Engine&lt;/a&gt; (GAE), local environment&lt;/li&gt;&lt;li&gt;Identify roles: developer, designer, QA, manager, presenter&lt;/li&gt;&lt;li&gt;Database: relational, NoSQL (GAE)&lt;/li&gt;&lt;li&gt;Scaffolding for rapid application development (RAD):&lt;ul&gt;&lt;li&gt;Java: &lt;a href="http://www.springsource.org/roo" target="new"&gt;Spring Roo&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Groovy: &lt;a href="http://www.grails.org/Scaffolding" target="new"&gt;Grails&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Ruby: &lt;a href="http://www.tutorialspoint.com/ruby-on-rails/rails-scaffolding.htm" target="new"&gt;Rails&lt;/a&gt;&lt;/li&gt;&lt;li&gt;PHP: &lt;a href="http://www.phpscaffold.com/" target="new"&gt;phpScaffold&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Requirements gathering techniques: wireframes, use cases&lt;/li&gt;&lt;li&gt;Task management: whiteboard, electronic&lt;/li&gt;&lt;li&gt;Pre-designed templates for common functionality: Home page, dashboards, login, reports&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Multiple Platform Strategy&lt;/h3&gt;&lt;p&gt;When I initially saw the 10 member team size I knew that could lead to inefficiencies.  Often a team of 3-6 is an ideal size.  To remedy this issue why not split the team into two smaller sub-groups?  Have one group focus on a desktop Web solution and the other on a mobile Web solution.  I see two huge advantages of this strategy.  First, it should help eliminate critical paths.  Again, with ten team members I see too many members waiting idle for others to complete dependent tasks.  And most importantly, this strategy should help deliver that extra punch to help wow the judges.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Execution Strategy&lt;/h3&gt;&lt;p&gt;Prior to the competition, every developer and designer must have a fully integrated development environment.  Everyones environment must build a template project, sync to the repository, and deploy to the production-ready hosting environment.  Once competition begins the focus must be solely about requirements gathering, task definition, prioritization, and efficient implementation.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Kudos&lt;/h3&gt;&lt;p&gt;I wanted to thank the &lt;a href="http://nerdery.com/" target="new"&gt;Nerdery&lt;/a&gt; for hosting such a unique event in the Twin Cities!  This is 100% voluntary and the solutions are built for non-profits!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-192554129985119841?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/192554129985119841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2011/02/agile-strategy-for-24-hour-coders.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/192554129985119841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/192554129985119841'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2011/02/agile-strategy-for-24-hour-coders.html' title='Agile Strategy for 24-hour Coders Challenge'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-Ca53h6Q6ecU/TVNO8zsXnzI/AAAAAAAAAHc/FkL1jAnswNQ/s72-c/R_C_Wall_Clock.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-3264372863318327976</id><published>2011-01-16T15:34:00.001-06:00</published><updated>2011-01-16T15:43:31.743-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>JavaScript Performance: Creational Patterns</title><content type='html'>Which JavaScript creational pattern is the most efficient?  Is it an object literal, functional, or pseudoclassical object?  With &lt;a href="http://code.google.com/p/js-test-driver/" target="new"&gt;JsTestDriver&lt;/a&gt;, I setup a quick performance test to gather the metrics.  &lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;h3&gt;Creational Patterns to Test&lt;/h3&gt;I tested the three most popular creational patterns in JavaScript.  Object literals, functional objects, and pseudoclassical objects.  In particular, I wanted to test their singleton and instance based execution times.&lt;br /&gt;&lt;pre&gt;&lt;span class="code-highlight1"&gt;/*&lt;br /&gt; * Pseudoclassical object designed as a singleton&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;var&lt;/span&gt; PseudoclassicalSingleton = &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;new function&lt;/span&gt;(){&lt;br /&gt;    &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;this&lt;/span&gt;.getName = &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){&lt;br /&gt;        &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;return&lt;/span&gt; &lt;span style="color: rgb(51, 102, 204);"&gt;'Pseudoclassical'&lt;/span&gt;;&lt;br /&gt;    };&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span class="code-highlight1"&gt;/*&lt;br /&gt; * Functional object designed as a singleton&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;var&lt;/span&gt; FunctionalSingleton = (&lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){&lt;br /&gt;    &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;return&lt;/span&gt; {&lt;br /&gt;        getName: &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){&lt;br /&gt;            &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;return&lt;/span&gt; &lt;span style="color: rgb(51, 102, 204);"&gt;'Functional'&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;})();&lt;br /&gt;&lt;br /&gt;&lt;span class="code-highlight1"&gt;/*&lt;br /&gt; * Object literal (implicitly singleton)&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;var&lt;/span&gt; ObjectLiteralSingleton = {&lt;br /&gt;    getName: &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){&lt;br /&gt;        &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;return&lt;/span&gt; &lt;span style="color: rgb(51, 102, 204);"&gt;'ObjectLiteral'&lt;/span&gt;;&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span class="code-highlight1"&gt;/*&lt;br /&gt; * Pseudoclassical object designed as a non-singleton&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;var&lt;/span&gt; PseudoclassicalInstance = function(){&lt;br /&gt;    &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;this&lt;/span&gt;.getName = &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){&lt;br /&gt;        &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;return&lt;/span&gt; &lt;span style="color: rgb(51, 102, 204);"&gt;'Pseudoclassical'&lt;/span&gt;;&lt;br /&gt;    };&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;span class="code-highlight1"&gt;/*&lt;br /&gt; * Functional object designed as a non-singleton&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;var&lt;/span&gt; FunctionalInstance = function(){&lt;br /&gt;    &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;return&lt;/span&gt; {&lt;br /&gt;        getName: &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){&lt;br /&gt;            &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;return&lt;/span&gt; &lt;span style="color: rgb(51, 102, 204);"&gt;'Functional'&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Performance Test Runner&lt;/h3&gt;I setup &lt;a href="http://code.google.com/p/js-test-driver/" target="new"&gt;JsTestDriver&lt;/a&gt; to execute the test cases against Firefox.  One advantage of JsTestDriver is I can run my test cases against &lt;em&gt;any&lt;/em&gt; browser!  Each performance test will instantiate its creational pattern 1.4 million times as indicated by the &lt;em&gt;RUN_TIMES&lt;/em&gt; constant.   Additionally, I ran the performance test suite twenty times to gather an adequate average. &lt;br /&gt;&lt;pre&gt;CreationalPatternsPerformanceTest = TestCase(&lt;span style="color: rgb(51, 102, 204);"&gt;"CreationalPatternsPerformanceTest"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;var&lt;/span&gt; RUN_TIMES = &lt;span style="color: rgb(51, 102, 204);"&gt;1400000&lt;/span&gt;; &lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;var&lt;/span&gt; performanceTest = &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(name, f){&lt;br /&gt;    console.time(name);&lt;br /&gt;    &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;var&lt;/span&gt; i = &lt;span style="color: rgb(51, 102, 204);"&gt;0&lt;/span&gt;; i &lt; RUN_TIMES; i++){&lt;br /&gt;        f();&lt;br /&gt;    }&lt;br /&gt;    console.timeEnd(name);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;CreationalPatternsPerformanceTest.prototype.testResponseTimes = &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){&lt;br /&gt;    performanceTest(&lt;span style="color: rgb(51, 102, 204);"&gt;"ObjectLiteral (singleton)"&lt;/span&gt;, &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){ &lt;br /&gt;        ObjectLiteralSingleton.getName(); &lt;br /&gt;    });&lt;br /&gt;    performanceTest(&lt;span style="color: rgb(51, 102, 204);"&gt;"Pseudoclassical (singleton)"&lt;/span&gt;, &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){ &lt;br /&gt;        PseudoclassicalSingleton.getName(); &lt;br /&gt;    });&lt;br /&gt;    performanceTest(&lt;span style="color: rgb(51, 102, 204);"&gt;"Functional (singleton)"&lt;/span&gt;, &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){ &lt;br /&gt;        FunctionalSingleton.getName(); &lt;br /&gt;    });&lt;br /&gt;    performanceTest(&lt;span style="color: rgb(51, 102, 204);"&gt;"Pseudoclassical (instance)"&lt;/span&gt;, &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){ &lt;br /&gt;        new PseudoclassicalInstance().getName(); &lt;br /&gt;    });&lt;br /&gt;    performanceTest(&lt;span style="color: rgb(51, 102, 204);"&gt;"Functional (instance)"&lt;/span&gt;, &lt;span style="color: rgb(0, 51, 102); font-weight:bold"&gt;function&lt;/span&gt;(){ &lt;br /&gt;        FunctionalInstance().getName(); &lt;br /&gt;    });&lt;br /&gt;};&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;caption&gt;&lt;strong&gt;Performance Test Results&lt;/strong&gt;&lt;/caption&gt;&lt;tr&gt;&lt;th&gt;&amp;nbsp;&lt;/th&gt;&lt;br /&gt;&lt;th style="text-align:center;"&gt;Object Literal (singleton)&lt;/th&gt;&lt;th style="text-align:center;"&gt;Pseudoclassical (singleton)&lt;/th&gt;&lt;th style="text-align:center;"&gt;Functional (singleton)&lt;/th&gt;&lt;th style="text-align:center;"&gt;Pseudoclassical (instance)&lt;/th&gt;&lt;th style="text-align:center;"&gt;Functional (instance)&lt;/th&gt;&lt;/tr&gt;&lt;tr class="alt"&gt;&lt;th style="text-align:center;"&gt;Avg (ms)&lt;/th&gt;&lt;td style="text-align:center; font-weight:bold; color:green"&gt;1093&lt;/td&gt;&lt;td style="text-align:center; font-weight:bold; color:green"&gt;1095&lt;/td&gt;&lt;td style="text-align:center; font-weight:bold; color:green"&gt;1094&lt;/td&gt;&lt;td style="text-align:center; font-weight:bold; color:red"&gt;3301&lt;/td&gt;&lt;td style="text-align:center; font-weight:bold; color:red"&gt;3341&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th style="text-align:center;"&gt;Min (ms)&lt;/th&gt;&lt;td style="text-align:center;"&gt;1070&lt;/td&gt;&lt;td style="text-align:center;"&gt;1064&lt;/td&gt;&lt;td style="text-align:center;"&gt;1062&lt;/td&gt;&lt;td style="text-align:center;"&gt;3225&lt;/td&gt;&lt;td style="text-align:center;"&gt;3246&lt;/td&gt;&lt;/tr&gt;&lt;tr class="alt"&gt;&lt;th style="text-align:center;"&gt;Max (ms)&lt;/th&gt;&lt;td style="text-align:center;"&gt;1112&lt;/td&gt;&lt;td style="text-align:center;"&gt;1114&lt;/td&gt;&lt;td style="text-align:center;"&gt;1113&lt;/td&gt;&lt;td style="text-align:center;"&gt;3460&lt;/td&gt;&lt;td style="text-align:center;"&gt;3476&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;h3&gt;Areas of Interest&lt;/h3&gt;&lt;br /&gt;I had three specific comparisons I wanted to evaluate heading into this experiment:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Object literals vs the others (functional and pseudoclassical):&lt;/strong&gt;  I knew object literals were going to be the most efficient.  However, I really wanted to see how &lt;em&gt;much faster&lt;/em&gt; they really are.  The result was surprising.  Object literals (1093 ms) barely out performed functional (1094 ms) and pseudoclassical (1095 ms) response times.  This difference is really negligible.  Unlike object literals, functional and pseudoclassical objects can provide security.  And the performance degradation is almost non-existent.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Functional vs Pseudoclassical:&lt;/strong&gt;  There are always &lt;a href="http://www.bolinfest.com/javascript/inheritance.php" target="new"&gt;debates&lt;/a&gt; over these two objects.  While I personally prefer pseudoclassical objects when security is a concern I definitely wanted to see which one was the more performant option.  In the end, neither pattern distanced itself from the other in regards to performance.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Singletons vs Instance based Objects:&lt;/strong&gt;  I knew singletons would be the most efficient.  However, I wanted to see what this difference really was.  On average, singletons were &lt;em&gt;three times&lt;/em&gt; faster.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Lessons Learned&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;Prefer singletons over instance based objects when possible.&lt;/li&gt;&lt;li&gt;Prefer object literals when you are &lt;em&gt;not&lt;/em&gt; concerned about privacy.&lt;/li&gt;&lt;li&gt;The performance metrics alone are not enough to sway the functional vs pseudoclassical debate.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-3264372863318327976?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/3264372863318327976/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/11/javascript-performance-creational.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3264372863318327976'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3264372863318327976'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/11/javascript-performance-creational.html' title='JavaScript Performance: Creational Patterns'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-3933053314392629500</id><published>2011-01-02T18:46:00.000-06:00</published><updated>2011-01-02T18:46:17.099-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>JavaScript: Securing Pseudoclassical Objects</title><content type='html'>Which JavaScript pattern do you prefer for object creation?  Functional or pseudoclassical?  This question makes for a very interesting debate.  The first time I read &lt;a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742" target="new"&gt;JavaScript: The Good Parts&lt;/a&gt; I was sold on the &lt;a href="http://sp4.us/jsbook/functional.html" target="new"&gt;functional pattern&lt;/a&gt; based upon the knowledge that it was the only pattern that supported privacy.  However, the &lt;a href="http://sp4.us/jsbook/pseudoclassical.html" target="new"&gt;pseudoclassical pattern&lt;/a&gt; can be secured!  Based upon the fact that &lt;em&gt;pseudoclassical objects can be secured&lt;/em&gt; and its many &lt;a href="http://www.bolinfest.com/javascript/inheritance.php" target="new"&gt;additional advantages&lt;/a&gt; make it the ideal choice for object creation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Securing Pseudoclassical Objects&lt;/h3&gt;&lt;pre&gt;&lt;span class="code-highlight1"&gt;/**&lt;br /&gt; * Pseudoclassical object with private variables and functions.&lt;br /&gt; *&lt;br /&gt; * @constructor &lt;br /&gt; * @param {string} name&lt;br /&gt; * @param {number} age&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;var Person = function(name, age) {&lt;br /&gt; &lt;br /&gt;     &lt;span class="code-highlight1"&gt;/** @public variable */&lt;/span&gt;&lt;br /&gt;     this.name = name || 'Brad';&lt;br /&gt; &lt;br /&gt;     &lt;span class="code-highlight1"&gt;&lt;strong&gt;/** @private variable */&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;     var age = age || 34; &lt;br /&gt; &lt;br /&gt; &lt;br /&gt;     &lt;span class="code-highlight1"&gt;&lt;strong&gt;/** @private function */&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;     function setAge(a) { &lt;br /&gt;         age = a;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     &lt;span class="code-highlight1"&gt;/** @public function with access to private methods and variables (privileged) */&lt;/span&gt;&lt;br /&gt;     this.getAge = function () {&lt;br /&gt;         return age;&lt;br /&gt;     };&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Why is Everything Public?&lt;/h3&gt;Security is not often documented within JavaScript books and I rarely see examples where developers secure their JavaScript objects.  Typically, everything is exposed publicly.  If you develop mobile applications with &lt;a href="http://www.appcelerator.com/" target="new"&gt;Titanium&lt;/a&gt; or are developing a JavaScript framework you absolutely must apply security with either the functional or pseudoclassical pattern.  And of all the Titanium code I have read over the past month not a single example or sample application was concerned about privacy.  Training can remedy this problem.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;JavaScript Code Completion&lt;/h3&gt;&lt;img style="float:right; width: 196px; height: 162px;" src="http://4.bp.blogspot.com/_mO_Jjc1RwAQ/TSEMD6GdLBI/AAAAAAAAAHQ/eSfC8U6f6IU/s400/autocomplete.png" border="1" alt="auto complete" /&gt;A simple way to quickly view the publicly available methods of an object is with code completion.  For example, the &lt;a href="http://www.aptana.com/" target="new"&gt;Aptana&lt;/a&gt; Eclipse plug-in has code completion built-in and works very well for JavaScript development.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-3933053314392629500?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/3933053314392629500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/10/javascript-securing-pseudoclassical.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3933053314392629500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3933053314392629500'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/10/javascript-securing-pseudoclassical.html' title='JavaScript: Securing Pseudoclassical Objects'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_mO_Jjc1RwAQ/TSEMD6GdLBI/AAAAAAAAAHQ/eSfC8U6f6IU/s72-c/autocomplete.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-1613902299459531601</id><published>2010-11-29T18:29:00.003-06:00</published><updated>2010-11-29T19:15:22.846-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>Becoming a MacBook Pro Ninja</title><content type='html'>&lt;img style="border:0px; float:right; margin:-20px 0px -20px 10px; width: 175px; height:&lt;br /&gt;175px;" src="http://2.bp.blogspot.com/_mO_Jjc1RwAQ/TO8Wx915udI/AAAAAAAAAHE/viMw3vLJyFM/s400/mac-book-pro1.jpg" border="0" alt="mac book pro" /&gt;I have always been the &lt;strong&gt;&lt;span style="font-style:italic;"&gt;PC&lt;/span&gt;&lt;/strong&gt; guy in those funny Mac&lt;br /&gt;commercials.  I knew very little about Macs a month ago.  In fact, I had to consult the owners manual to find the seamlessly integrated power button on the shiny new Mac Book Pro!  I didn't feel too bad, I challenged another PC guy to find it and they failed too:)  Being a novice at anything can be extremely frustrating.  As a novice I set a simple goal.  Learn everything about this all-aluminum, uni body machine.  After reading &lt;a href="http://www.amazon.com/MacBook-Portable-Genius-Brad-Miser/dp/0470291702" target="new"&gt;MacBook Pro Portable Genius&lt;/a&gt;, a few magazines, and many online tips I finally feel very comfortable in the drivers seat.  Here is a very brief recap of what I discovered on my journey.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Favorite Features&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.apple.com/macbookpro/features.html#overlay-trackpad" target="new"&gt;Trackpad gestures&lt;/a&gt;: &lt;br /&gt;The trackpad is unquestionably the most powerful feature you will find on any laptop and it is exclusive to MacBooks.  Who needs a mouse?  I am more efficient with the trackpad!  &lt;span style="font-style:italic;"&gt;Enable "tap to click" for even greater efficiency gains.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Exposé_(Mac_OS_X)" target="new"&gt;Expose&lt;/a&gt;: &lt;br /&gt;Expose is also totally unique to Macs and offers a convenient layout for switching between open windows.  Additionally, Application Switcher and Spaces (also unique) each offer efficient capabilities for navigating your workspace.  These features will definitely make you more efficient while multitasking.&lt;/li&gt;&lt;li&gt;Security: &lt;br /&gt;The security settings are powerful and simple to setup.  The settings include: account management, password enforcement, data encryption, firewall protection, secure notes, SSO capabilities, and parental controls.  Each can be configured within Settings or &lt;a href="http://en.wikipedia.org/wiki/Keychain_(Mac_OS)" target="new"&gt;Key Chain&lt;/a&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h3&gt;Top Four Things To Customize When Setting Up&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;Enable Firewall:&lt;br /&gt;If you access public WIFI, setting up your firewall is a must.  WIFI is the &lt;a href="http://bradbroulik.blogspot.com/2010/04/mobile-security-hacks-to-avoid.html" target="new"&gt;most vulnerable network&lt;/a&gt; you can access.  Configure your settings to be most restrictive (block all incoming connections) and adjust as necessary if you need to allow network or web sharing.&lt;/li&gt;&lt;li&gt;Require Passwords: &lt;br /&gt;Most users disable passwords on personal devices for convenience.  I will always opt for security.&lt;/li&gt;&lt;li&gt;Enable File Vault Encryption: &lt;br /&gt;This encrypts the entire home directory.  I searched for benchmark studies and they only revealed minor performance degradation.  If my laptop ends up in the wrong hands at least the malicious user won't be able to login or physically read my hard drive.&lt;/li&gt;&lt;li&gt;Adjust Energy Savings: &lt;br /&gt;Dim the backlit keyboard, reduce screen brightness, and adjust the energy saver settings to preserve battery life.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;h3&gt;Most Frustrating Features&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Speech recognition:  &lt;br /&gt;This is an interesting feature that is hit or miss.  A few commands work well ("open my browser") while others rarely work ("tell me a joke").  In the end, the trackpad reigns supreme.&lt;/li&gt;&lt;li&gt;No trackpad gesture for Spaces:  &lt;br /&gt;Looks like the only alternative is to use a hot corner or keyboard shortcut.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Features With Potential That I May Never Use&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Dashboard: &lt;br /&gt;I have setup several active widgets for weather and iTunes but I can access these features outside of dashboard too.  The availability of useful widgets will drive my usage of this feature.&lt;/li&gt;&lt;li&gt;Text-to-speech:  &lt;br /&gt;This is a nice feature but I only see myself using it while reading an online book.&lt;/li&gt;&lt;li&gt;MobileMe:  &lt;br /&gt;I can not justify the yearly cost for Apple's cloud storage when a simple flash drive does the job at a lower cost.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Mac Book Resources&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/MacBook-Portable-Genius-Brad-Miser/dp/0470291702" target="new"&gt;MacBook Pro Portable Genius&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://support.apple.com/kb/ht1343" target="new"&gt;Keyboard Shortcuts&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.myfavouritemagazines.co.uk/computer/make-the-most-out-of-your-Mac-2nd-edition/" target="new"&gt;Make the Most Out of Your Mac&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.apple.com/pro/tips/" target="new"&gt;Apple Pro Tips Archive&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-1613902299459531601?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/1613902299459531601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/11/becoming-macbook-pro-ninja.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1613902299459531601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1613902299459531601'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/11/becoming-macbook-pro-ninja.html' title='Becoming a MacBook Pro Ninja'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_mO_Jjc1RwAQ/TO8Wx915udI/AAAAAAAAAHE/viMw3vLJyFM/s72-c/mac-book-pro1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-4001735091957221239</id><published>2010-09-14T19:36:00.027-05:00</published><updated>2010-09-15T22:08:15.276-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>Cleaner Code with One Simple Technique</title><content type='html'>&lt;div style='float:right; margin:-54px 0px 0px 0px;'&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://bradbroulik.blogspot.com/2010/09/cleaner-code-with-one-simple-technique.html';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Cleaner Code with One Simple Technique';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;img style="border:0px; float:right;width: 108px; height: 144px;" border="0" src="http://2.bp.blogspot.com/_mO_Jjc1RwAQ/TIqoDth3nfI/AAAAAAAAAG8/sclahAet_W8/s400/clean-code-image.jpg" border="0" alt="Clean code book" /&gt;What is the simplest technique you can apply to write cleaner code?  &lt;a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1284157809&amp;sr=8-1" target="new"&gt;Clean Code&lt;/a&gt; by Robert C. Martin is a very good book that focuses exclusively on writing cleaner code.  I read this book several months ago and at a recent code review I was again reminded of the value of this simple technique.  The simplest technique to apply for writing cleaner code is to &lt;strong&gt;&lt;em&gt;keep functions small!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Advantages of Small Functions&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Functions perform one specific responsibility (single responsibility principle)&lt;/li&gt;&lt;li&gt;Functions become very readable&lt;/li&gt;&lt;li&gt;Functions are more likely to descend only one level of abstraction (tip G34 from Bob's book)&lt;/li&gt;&lt;li&gt;Small functions promote reusability and help eliminate duplication&lt;/li&gt;&lt;li&gt;Your favorite IDE makes extract method so simple&lt;/li&gt;&lt;li&gt;Small functions adhere to these valuable coding principles by design&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Ideal Function Size&lt;/h3&gt;&lt;p&gt;"Continue to extract methods until you can not extract methods anymore.  Extract until you drop!"  This is Bob's recommendation from his online presentation of &lt;a href="http://www.infoq.com/presentations/Robert-C.-Martin-Bad-Code" target="new"&gt;Bad Code and Craftsmanship&lt;/a&gt;.  Personally, I couldn't agree more.  For the past three months I have been following this practice and this simple technique has a high return on investment.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Additional Clean Code Tips&lt;/h3&gt;&lt;p&gt;Looking for additional clean code tips?  Chapter 17 (Smells and Heuristics) in Bob's &lt;a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1284157809&amp;sr=8-1" target="new"&gt;book&lt;/a&gt; is a very quick read and covers sixty-six valuable coding practices.  Alternatively, Bob discusses many clean code practices in his &lt;a href="http://www.infoq.com/presentations/Robert-C.-Martin-Bad-Code" target="new"&gt;online presentation&lt;/a&gt;.  In fact, he leads off the discussion by focusing on the importance of small functions!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-4001735091957221239?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/4001735091957221239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/09/cleaner-code-with-one-simple-technique.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/4001735091957221239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/4001735091957221239'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/09/cleaner-code-with-one-simple-technique.html' title='Cleaner Code with One Simple Technique'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_mO_Jjc1RwAQ/TIqoDth3nfI/AAAAAAAAAG8/sclahAet_W8/s72-c/clean-code-image.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-1769203543166447536</id><published>2010-08-31T16:35:00.025-05:00</published><updated>2010-08-31T17:00:25.885-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>Objective-C for Java Developers</title><content type='html'>&lt;img src="http://2.bp.blogspot.com/_mO_Jjc1RwAQ/THp090FWJ0I/AAAAAAAAAGk/qNJ1I1BxZgk/s400/objective-c-book-image.png" border="0" style="border: 0px; width: 125px; height: 165px; float:right;" alt="objective c book" /&gt;&lt;br /&gt;&lt;br /&gt;I actually won &lt;a href="http://www.apress.com/book/view/1430223693" target="new"&gt;Learn Objective-C for Java Developers&lt;/a&gt; at the last Twin Cities Java User group &lt;a href="http://www.intertech.com/UserGroups/JUGPresentation.aspx?TopicID=150" target="new"&gt;meeting&lt;/a&gt;.  The only stipulation for winning a free book is the expectation that we publish a review of the book online.  This is  a small task for a free book.  Learning Objective-C has been on my &lt;em&gt;todo&lt;/em&gt; list for several months anyway.  Winning this book simply moved it higher on my priority list. &lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;h3 style="float:left"&gt;Review:&lt;/h3&gt;&lt;img style="float:left; margin-top:-5px; border:0px; width:65px; height: 20px;" src="http://2.bp.blogspot.com/_mO_Jjc1RwAQ/THp8IrPbIPI/AAAAAAAAAGs/G6lMsTY9lWI/s400/4-stars.png" border="0" alt="4 star rating" /&gt;&lt;br&gt;&lt;h4&gt;Pros:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Many of the Objective-C examples were also shown with their Java counterpart.  This added value in two regards.  First, it clarified what the example was really doing.  I could simply reference the Java version and quickly understand the Objective-C code.  Secondly, it allowed me to compare and contrast the two languages.  In many cases (but not all) the Objective-C examples contained fewer lines of code.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;In addition to the Java and Objective-C examples, the book also had many table-based comparisons for common features (data types, methods).  For example, one page listed the Java data types and their Objective-C alternative including their size and range restrictions.  Again this helped simplify the learning curve.  The table-based charts were also used for common method declarations too.  For example, the common String utility methods were shown side-by-side.  One column showing Java's String utility method declarations and the other column showing the Objective-C alternative.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Most code examples were a page or less.  This helped simplify the learning process by allowing me to focus on more isolated code fragments.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Cons:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Many books that teach a new programming language typically include exercises at the end of each chapter that the reader can take away and complete.  This book did not have any.  This is a minor complaint.  I can definitely think of sample programs to write...&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The index does not always serve as a good reference for finding things quickly.  For example, I wanted to find more information about logging and "logging" or "NSLog" were not in the index.  Need to find the for loop quickly?  You will not find it in the index.  It is actually found in the index under "Collections, iterating through".  The index could have been structured slightly better for quick search keywords.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;An Objective-C quick reference guide would have been helpful.  This did not bother me too much because about the time I started reading this book DZone released a new &lt;a href="http://refcardz.dzone.com/refcardz/objective-c-iphone-and-ipad" target="new"&gt;Objective-C reference guide&lt;/a&gt;.  I highly recommend it!  In my previous "con" I mentioned that it can be painful to find certain topics (logging, data types, loops) quickly within the index.  The DZone refcard provides quick access to those topics and more!&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Summary&lt;/h4&gt;&lt;p&gt;Overall this book is a very valuable resource for Java developers that want to learn the Objective-C language.  The author greatly simplifies the Objective-C learning curve by contrasting many features and examples to its Java equivalent.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-1769203543166447536?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/1769203543166447536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/08/objective-c-for-java-developers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1769203543166447536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1769203543166447536'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/08/objective-c-for-java-developers.html' title='Objective-C for Java Developers'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_mO_Jjc1RwAQ/THp090FWJ0I/AAAAAAAAAGk/qNJ1I1BxZgk/s72-c/objective-c-book-image.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-3781140796008828551</id><published>2010-07-31T11:52:00.011-05:00</published><updated>2010-09-15T21:55:28.614-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><title type='text'>Mobile Web Toolkit</title><content type='html'>&lt;div style='float:right; margin:-30px 0px 0px 0px;'&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://bradbroulik.blogspot.com/2010/07/mobile-web-toolkit.html';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Mobile Web Toolkit';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://3.bp.blogspot.com/_mO_Jjc1RwAQ/TFRNXRBH-nI/AAAAAAAAAGc/ZMvvwFwnt5c/s400/droidx1.png" border="1" style="border: 1px solid rgb(204, 204, 204); width: 65px; height: 140px; float:right;" alt="mobile phone" /&gt;Mobile Web development requires a more abundant set of developer tools than its desktop counterpart.  XHTML MP, Wireless CSS, and Mobile JavaScript are all more refined subsets compared to their desktop predecessors.  In addition, the Mobile Web offers many new challenges.  In particular, device fragmentation and browser inconsistencies will always wreak havoc within this ecosystem.  Great tools can help overcome these challenges. Here are a few: &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Validating Mobile Sites&lt;/h3&gt;How valid is your Mobile Web Site?  Find out with these awesome validators.  These validators will grade and offer best practice solutions to achieve a more compliant Mobile site.  These are also valuable tools for a code review!&lt;ul&gt;&lt;li&gt;&lt;a href="http://validator.w3.org/mobile/" target="new"&gt;W3C mobileOK Checker&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://ready.mobi/" target="new"&gt;dotMobi's mobile validator&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mobile Web Best Practices&lt;/h3&gt;Both validators above evaluate mobile sites based upon standards and best practices.  Their best practice and standards documentation can be found here:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.w3.org/TR/mobile-bp/" target="new"&gt;W3C's Mobile Web Best Practices&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://mobiforge.com/starting/story/dotmobi-mobile-web-developers-guide" target="new"&gt;dotMobi's Mobile Web Developers Guide&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Device Databases&lt;/h3&gt;Device databases simplify device detection.  This helps facilitate content adaptation for specific device groupings (smartphones, featurephones, screen size, OS, JavaScript/AJAX support, is wireless, is touchscreen, etc.).  For example, &lt;a href="https://www.bankofamerica.com/mobile" target="new"&gt;Bank of America&lt;/a&gt; and &lt;a href="http://www.amazon.com/" target="new"&gt;Amazon&lt;/a&gt; tailor content based on several of these groupings.&lt;ul&gt;&lt;li&gt;&lt;a href="http://wurfl.sourceforge.net/" target="new"&gt;WURFL&lt;/a&gt; (open source)&lt;/li&gt;&lt;li&gt;&lt;a href="http://deviceatlas.com/" target="new"&gt;DeviceAtlas&lt;/a&gt; (commercial)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;XHTML Mobile Profile&lt;/h3&gt;&lt;a href="http://en.wikipedia.org/wiki/XHTML_Mobile_Profile"&gt;XHTML MP&lt;/a&gt; is the standard markup language for the Mobile Web.  Unlike HTML and XHTML, XHTML-MP is featurephone compatible, it is less likely to be transcoded for optimization, and it supports the mobile-optimized Wireless CSS and Mobile JavaScript features.  For additional XHTML MP 1.2 features refer to OMA's &lt;a href="http://users.jyu.fi/~mweber/teaching/docs/xhtml-mp/OMA-XHTMLMP-V1_2-20041222-D.pdf" target="new"&gt;specification document&lt;/a&gt;.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Firefox Add-ons&lt;/h3&gt;The following Firefox add-ons are &lt;em&gt;very&lt;/em&gt; powerful tools for testing and developing:&lt;ul&gt;&lt;li&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/59/" target="new"&gt;User Agent Switcher&lt;/a&gt; allows you to alter your user-agent.  Now you can simulate a request as any device.  For example, I used this technique to test the content adaptation on &lt;a href="https://www.bankofamerica.com/mobile" target="new"&gt;Bank of America&lt;/a&gt;.  They alter their content for touchscreen vs non-touchscreen devices.  Typically, it is a good practice to provide larger buttons on a touchscreen device.&lt;/li&gt;&lt;li&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/967/" target="new"&gt;Modify Headers&lt;/a&gt; allows you to alter your &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html" target="new"&gt;HTTP Headers&lt;/a&gt;.  This also allows us to simulate different types of device behavior. Additionally, if you need to &lt;a href="http://learnthemobileweb.com/tag/http-request-headers/" target="new"&gt;view HTTP Request Headers from a Mobile device&lt;/a&gt; &lt;a href="http://learnthemobileweb.com/" target="new"&gt;Gail Frederick&lt;/a&gt; has built a helpful site for that.&lt;/li&gt;&lt;li&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/1345/" target="new"&gt;XHTML Mobile Profile&lt;/a&gt; enables the Firefox browser to render XHTML MP markup documents.&lt;/li&gt;&lt;li&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/526/" target="new"&gt;Small Screen Renderer&lt;/a&gt; allows you to simulate the screen size of a mobile device.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Device Testing Solutions&lt;/h3&gt;The ideal testing solution is to &lt;em&gt;test on the physical device&lt;/em&gt;.    Two virtual device testing solutions exist:&lt;ul&gt;&lt;li&gt;&lt;a href="http://deviceanywhere.com/" target="new"&gt;DeviceAnywhere&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.perfectomobile.com/" target="new"&gt;Perfecto Mobile&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;JavaScript &amp; AJAX Compatibility&lt;/h3&gt;When device testing is not always feasible, the compatibility tables generated by &lt;a href="http://quirksmode.org/about/" target="new"&gt;Peter-Paul Koch&lt;/a&gt; are a good alternative.  If you need assistance identifying JavaScript compatibility across browsers or devices these tables can definitely help: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://quirksmode.org/m/table.html" target="new"&gt;JavaScript Mobile Compatibility Tables&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://pwmwa.com/frost/" target="new"&gt;Test AJAX compatibility on a mobile device&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://ajax.mobiletech.mobi/" target="new"&gt;Test AJAX and JavaScript compatibility on mobile device&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;CSS Compatibility&lt;/h3&gt;If you need assistance identifying CSS compatibility across browsers or devices these tables exit too:&lt;ul&gt;&lt;li&gt;&lt;a href="http://quirksmode.org/m/css.html" target="new"&gt;CSS Mobile Compatibility Tables&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://quirksmode.org/webkit.html" target="new"&gt;WebKit CSS Comparison Table&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://jigsaw.w3.org/css-validator/" target="new"&gt;W3C CSS Validation Service&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.developershome.com/wap/wcss/" target="new"&gt;Wireless CSS&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Web Widgets&lt;/h3&gt;Web Widgets will allow Mobile Web developers to take advantage of native phone features.  The subset is limited but it is a start: &lt;a href="http://www.w3.org/2009/dap/" target="new"&gt;Device APIs and Policy Working Group&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Book Resources&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Beginning-Smartphone-Web-Development-Applications/dp/143022620X/ref=pd_sim_b_3" target="new"&gt;Beginning Smartphone Web Development&lt;/a&gt;:  I highly recommend Chapter 8, Optimizing Mobile Markup and Chapter 12, How to Play Well in the Mobile Ecosystem&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Mobile-Design-Development-Practical-Techniques/dp/0596155441/ref=pd_bxgy_b_img_b" target="new"&gt;Mobile Design and Development&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Pro-Smartphone-Cross-Platform-Development-Distribution/dp/1430228687/ref=sr_1_1?s=books&amp;ie=UTF8&amp;qid=1280250726&amp;sr=1-1" target="new"&gt;Pro Smartphone Cross-Platform Development&lt;/a&gt; (Release Date: Aug 2010)&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-3781140796008828551?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/3781140796008828551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/07/mobile-web-toolkit.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3781140796008828551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3781140796008828551'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/07/mobile-web-toolkit.html' title='Mobile Web Toolkit'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_mO_Jjc1RwAQ/TFRNXRBH-nI/AAAAAAAAAGc/ZMvvwFwnt5c/s72-c/droidx1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-3045012747361617223</id><published>2010-06-30T18:33:00.012-05:00</published><updated>2010-07-31T11:26:41.005-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web services'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Restful Link Integrity</title><content type='html'>&lt;img src="http://1.bp.blogspot.com/_mO_Jjc1RwAQ/TCvTV1agHGI/AAAAAAAAAGU/7Dy9cAsE80k/s400/lock.jpg" border="1" style="border: 1px solid rgb(204, 204, 204); width: 125px; height: 125px; float:right;" alt="lock" /&gt;How do you secure sensitive information within your URIs?  Many of the RESTful examples I have seen expose sensitive information within their links.  Often this sensitive data is the identifying key of the entity that is being managed.  &lt;a href="http://www.amazon.ca/RESTful-Web-Services-Cookbook-Scalability/dp/0596801688" target=new&gt;RESTful Web Services Cookbook&lt;/a&gt; briefly discussed two solutions for securing sensitive information within URI's (refer to chapter 12 for details).  I will expand upon these two solutions by demonstrating how we can leverage the &lt;a href="http://www.jasypt.org/" target=new&gt;Jasypt&lt;/a&gt; encryption framework to preserve sensitive information.&lt;br /&gt;&lt;br /&gt;Initially, we must validate our URI templates do not expose sensitive data.  If they do not, there are no concerns.  However, if your URI templates expose sensitive data we must preserve their integrity and confidentiality.  An example of an insecure URI template may look like: &lt;br /&gt;&lt;br /&gt;&lt;em&gt;http://rest.com/account/{account_id}&lt;/em&gt;.  &lt;br /&gt;&lt;br /&gt;If this URI template exposes a clear text account ID we have a security gap.  If a security gap exists, we must implement a solution to preserve the integrity and confidentiality of the insecure URIs.  Three solutions exist to secure RESTful links:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Hashing&lt;/h3&gt;&lt;a href="http://en.wikipedia.org/wiki/Cryptographic_hash_function" target=new&gt;Hashing&lt;/a&gt; is an ideal solution if you need to expose data parameters in clear text and want to preserve &lt;a href="http://en.wikipedia.org/wiki/Message_integrity" target=new&gt;data integrity&lt;/a&gt;.  Integrity is the assertion that the data was not altered by the consumer or a man-in-the-middle.  With a hash-based solution the RESTful link may look like: &lt;br /&gt;&lt;br /&gt;&lt;em&gt;http://rest.com/account?account_id=123456&amp;digest=83r/grjAxjcqe5FE42xRgD6YF00q4DmsJALlfA==&lt;/em&gt; &lt;br /&gt;&lt;br /&gt;This solution will preserve integrity but it does &lt;em&gt;not&lt;/em&gt; provide confidentiality.  If the consumer or malicious user alters the account ID a server-side integrity check against the hash algorithm will fail.  The JUnit below demonstrates the creation of the digest (hash) and the assertion to validate the integrity of the clear text and digest have been preserved: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;@Test&lt;br /&gt;public void testJasyptsHashAlgorithm() {&lt;br /&gt; &lt;span class="code-highlight1"&gt;     /*&lt;br /&gt;       * By default the standard digester uses the RandomSaltGenerator and runs the hash&lt;br /&gt;       * algorithm 1000 times. These are configurable for greater security.&lt;br /&gt;       */&lt;/span&gt;&lt;br /&gt;      StandardStringDigester digester = new StandardStringDigester();&lt;br /&gt;      digester.setAlgorithm("SHA-1");&lt;br /&gt; &lt;br /&gt;      final String clearText = "123456";&lt;br /&gt;      final String digest = digester.digest(clearText);&lt;br /&gt;      Assert.assertTrue("Integrity has been violated!", digester.matches(clearText, digest));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Encryption&lt;/h3&gt;&lt;a href="http://en.wikipedia.org/wiki/Encryption" target=new&gt;Encryption&lt;/a&gt; is an ideal solution if you want to preserve integrity &lt;em&gt;and&lt;/em&gt; confidentiality.  For example, an encryption-based RESTful link may look like: &lt;br /&gt;&lt;br /&gt;&lt;em&gt;http://rest.com/account/kNddGYRn3KAWK5nYJ/5jrA==&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;The JUnit below demonstrates the creation of the encrypted text and the assertion to validate the integrity of the encrypted text has been preserved: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;@Test&lt;br /&gt;public void testJasyptsEncryptionAlgorithm() {&lt;br /&gt;      StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();&lt;br /&gt;      encryptor.setPassword("password");&lt;br /&gt;      encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); &lt;br /&gt; &lt;br /&gt;      final String clearText = "123456";&lt;br /&gt;      String encryptedText = encryptor.encrypt(clearText);&lt;br /&gt; &lt;br /&gt;      String decryptedText = null;&lt;br /&gt;      try {&lt;br /&gt;           decryptedText = encryptor.decrypt(encryptedText);&lt;br /&gt;      } catch (EncryptionOperationNotPossibleException e) {&lt;br /&gt;           Assert.fail("Integrity has been violated!");&lt;br /&gt;      }&lt;br /&gt;      Assert.assertEquals(clearText, decryptedText);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Do not expose sensitive data&lt;/h3&gt;The ideal solution is to not expose any sensitive information.  Alternatively, instead of exposing a sensitive primary key expose an associative key or index that has no identifying relationship to the entity.  A common scenario occurs when consumers need to search and maintain records.  Consider the following use case:  &lt;ol&gt;&lt;li&gt;User performs a search&lt;/li&gt;&lt;li&gt;The server-side executes the search and stores the list of authorized search results within session&lt;/li&gt;&lt;li&gt;The server only exposes the indexes of the entities the consumer is allowed to maintain:  &lt;em&gt;http://rest.com/account/{index_id}&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;This solution preserves integrity by restricting the user to only maintain the records they are authorized to manage and we do not expose a confidential primary key.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-3045012747361617223?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/3045012747361617223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/06/restful-link-integrity.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3045012747361617223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3045012747361617223'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/06/restful-link-integrity.html' title='Restful Link Integrity'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_mO_Jjc1RwAQ/TCvTV1agHGI/AAAAAAAAAGU/7Dy9cAsE80k/s72-c/lock.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-6075347448621902575</id><published>2010-06-16T05:54:00.002-05:00</published><updated>2010-06-16T05:58:17.851-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='database'/><title type='text'>NoSQL</title><content type='html'>&lt;img src="http://1.bp.blogspot.com/_mO_Jjc1RwAQ/TBg1A7RPPxI/AAAAAAAAAGM/KEcjmRt0SQA/s400/nosql.gif" border="1" style="border: 1px solid rgb(204, 204, 204); width: 150px; height: 100px; float:right;" alt="NoSQL" /&gt;What is the one language that has not changed since you learned it in college?  SQL is definitely one of them.  In fact, &lt;a href="http://en.wikipedia.org/wiki/SQL" target="new"&gt;SQL&lt;/a&gt; has only received minor updates over the past decade. For DBA's, this has been a luxury.  Is &lt;a href="http://en.wikipedia.org/wiki/NoSQL" target=new&gt;NoSQL&lt;/a&gt; positioned to change this stability?  NoSQL does not change SQL or relational databases, it simply provides a non-relational repository alternative.  The last &lt;a href="http://www.intertech.com/UserGroups/JUGPresentation.aspx?TopicID=148" target=new"&gt;Twin Cities Java User Group presentation&lt;/a&gt; given by Perry Hoekstra provided a very good summary of NoSQL's advantages and disadvantages.  Here is a recap:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Advantages&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Performance metrics have shown significant improvements vs relational access.  For example, this performance metric compares MySQL vs Cassandra:&lt;/li&gt;&lt;br /&gt;&lt;img src="http://3.bp.blogspot.com/_mO_Jjc1RwAQ/TBgzAEfYokI/AAAAAAAAAGE/OUDVTvqoBQI/s400/nosql-performance.gif" border="1" style="border: 1px solid rgb(204, 204, 204);" alt="NoSQL performance metric" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Inexpensive.  All NoSQL implementations except for Amazon's &lt;a href="http://en.wikipedia.org/wiki/Dynamo_%28storage_system%29" target=new"&gt;Dynamo&lt;/a&gt; are open source.&lt;/li&gt;&lt;li&gt;Data types are dynamic (typically strings).  However, each implementation defines their own data types.&lt;/li&gt;&lt;li&gt;Scales very well.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Disadvantages&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Bleeding Edge (right now).&lt;/li&gt;&lt;li&gt;Replication across a cluster is not guaranteed in real-time.  Synchronization will happen.  However, the "when" is currently documented as &lt;em&gt;unknown&lt;/em&gt;.&lt;/li&gt;&lt;li&gt;Third-party report tool (Business Objects, Cognos, etc.) integration is currently not available.&lt;/li&gt;&lt;li&gt;Data redundancy is likely to occur without relational tables.&lt;/li&gt;&lt;li&gt;The application code performs the SQL-like operations.&lt;/li&gt;&lt;li&gt;ORM capabilities do not exist yet.&lt;/li&gt;&lt;li&gt;Transaction capabilites do not exist yet.  However, &lt;a href="http://cassandra.apache.org/" target=new&gt;Cassandra&lt;/a&gt; will have this feature soon.&lt;/li&gt;&lt;li&gt;No GUI editor tool support.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Early Adopters of NoSQL&lt;/h3&gt;Social media corporations are the primary trailblazers of NoSQL implementations. The list includes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Facebook&lt;/li&gt;&lt;li&gt;Twitter&lt;/li&gt;&lt;li&gt;MySpace&lt;/li&gt;&lt;li&gt;Google (&lt;a href="http://hadoop.apache.org/" target=new&gt;Hadoop&lt;/a&gt;, &lt;a href="http://code.google.com/appengine/" target=new&gt;Google App Engine&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Amazon (Dynamo)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Resources&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://nosql.mypopescu.com/" target=new&gt;myNoSQL: The best daily NoSQL news&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.nosqldatabases.com/" target=new&gt;NoSQLDatabases.com&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://nosql-databases.org/" target=new&gt;NoSQL Databases&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-6075347448621902575?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/6075347448621902575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/06/nosql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/6075347448621902575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/6075347448621902575'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/06/nosql.html' title='NoSQL'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_mO_Jjc1RwAQ/TBg1A7RPPxI/AAAAAAAAAGM/KEcjmRt0SQA/s72-c/nosql.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-2396748380000109777</id><published>2010-05-23T09:42:00.001-05:00</published><updated>2010-05-23T09:43:06.919-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conferences'/><title type='text'>MinneBar 2010 Recap</title><content type='html'>&lt;a href="http://www.minnebar.org/minnebar/" target="new"&gt;Minnebar&lt;/a&gt; is an (un)conference aimed at getting those in Minnesota’s tech and design communities together to discuss topics that interest them.  This (un)conference is unique for several reasons. 1) It's free.  However, donations are welcome.  For $10 this was the cheapest tech conference I have ever attended.  2) Admission included: breakfast, lunch, snacks, &lt;em&gt;open bar&lt;/em&gt;, and of course 8 concurrent session to choose from!  &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Schedule&lt;/h3&gt;&lt;div style="border: 1px solid CCCCCC; overflow:auto; width:100%;"&gt;&lt;img src="http://3.bp.blogspot.com/_mO_Jjc1RwAQ/S_hy4tWiRxI/AAAAAAAAAF8/MyVm2kbF2aE/s1600/minnebar-schedule.jpg" /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Google Page Speed&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/speed/page-speed/" target=new&gt;Google Page Speed&lt;/a&gt; is similar to &lt;a href="http://developer.yahoo.com/yslow/" target=new&gt;YSlow&lt;/a&gt;.  It evaluates the performance of your website, displays the metrics, and lists optimization strategies to improve your score. It can be downloaded as a Firefox plug-in.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Room and Bored&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Is college broken when it comes to Information Technology?  This was the topic that was discussed.  Personally, I do not see anything broken with college.  However, it is very important to supplement real world experience with an IT degree.  For example, if you are in High School and want to pursue a career in IT then join your local IT community.  It's never too soon.  In addition, try finding part-time IT jobs or work for free.  There is no substitute for real world experience in addition to an awesome college degree.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;"I'm a guru not a God!" A Tao of System Architecture&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Characteristics of successful software systems were discussed.  Many common themes were discussed: KISS, don't reinvent the wheel, open/closed principle, etc.  In addition to those common traits the one characteristic that topped the list pertained to bureaucracy.  Mark Beckman noted that "bureaucracy is evil and should be severely limited".&lt;/li&gt;&lt;li&gt;"Bureaucracy frustrates people, distorts their priorities, limits their dreams and turns the face of the entire enterprise inward." -- Jack Welch, GE Annual Report, 2000&lt;/li&gt;&lt;li&gt;Lean processes are preferred.  We must eliminate the overhead of simple tasks.  How quickly can you deploy to production or setup a new development environment?  Is the process simple or not?  Cloud computing has few hurdles and provides an alternative for departments seeking simpler process.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mapping Your World with OpenStreetMap&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.openstreetmap.org/" target=new&gt;OpenStreetMap&lt;/a&gt; is a Wikipedia of maps allowing anyone to edit the map.  Now we can map our favorite tennis courts, hiking trails, or archery range!&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.toposm.com/" target=new"&gt;Topo maps&lt;/a&gt; are currently in development.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.cloudmade.com/" target=new&gt;Cloudmade&lt;/a&gt; can be used for driving directions&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Why Drupal?  An expert panel&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;&lt;a href="http://drupal.org/" target=new&gt;Drupal&lt;/a&gt; is an open source CMS solution.  If you are interested in Drupal, there is a &lt;a href="http://groups.drupal.org/twin-cities" target=new&gt;Twin Cities Drupal group&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Getting started with CSS3&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;New CSS3 features that you should be using today include:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.css3.info/preview/opacity/" target=new&gt;RGB colors with opacity&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.css3.info/border-radius-apple-vs-mozilla/" target=new&gt;border-radius&lt;/a&gt; for more elegant rounded corners&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.css3.info/preview/box-shadow/" target=new&gt;box-shadow&lt;/a&gt; for a drop shadow effect&lt;/li&gt;&lt;li&gt;&lt;a href="http://davidwalsh.name/css-tables-css3-alternate-row-colors" target=new&gt;tr:nth-child&lt;/a&gt; for alternate row colors&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Overall, Minnebar was a hit!  The attendance was extremely high with roughly 800-900 attendees.  The venue at Best Buy was fantastic.  However, next time they should increase the number of available WIFI hotspots.  The network was overloaded.  &lt;em&gt;I can't wait for the fall show!&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-2396748380000109777?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/2396748380000109777/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/05/minnebar-2010-recap.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/2396748380000109777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/2396748380000109777'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/05/minnebar-2010-recap.html' title='MinneBar 2010 Recap'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_mO_Jjc1RwAQ/S_hy4tWiRxI/AAAAAAAAAF8/MyVm2kbF2aE/s72-c/minnebar-schedule.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-8303409419005971120</id><published>2010-04-13T18:47:00.006-05:00</published><updated>2010-04-13T18:53:40.509-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Mobile Security Hacks to Avoid</title><content type='html'>The average cost of a data breach is &lt;a href="http://searchsecurity.techtarget.com/news/article/0,289142,sid14_gci1379486,00.html" target="new"&gt;$6.75 million&lt;/a&gt;.  While some argue that data breaches cannot be prevented, training and education can prove to be a very effective remedy.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Hacking-Next-Generation-Animal-Guide/dp/0596154577/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1270849342&amp;sr=1-1" target="new"&gt;Hacking: The Next Generation&lt;/a&gt; is an extremely good book filled with detailed examples on how hackers maliciously attack unsuspecting users.  While this book primarily discusses the offensive strategies hackers employ, I am going to discuss several countermeasures to help secure mobile users.  Mobile vulnerabilities typically fall under one or more of the following categories: &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;WIFI Hacks&lt;/h3&gt;&lt;br /&gt;TJ Maxx suffered a &lt;em&gt;&lt;a href="http://www.ebizq.net/blogs/news_security/2007/05/cost_of_tj_maxx_breach_in_the.php" target=new&gt;$4.5 billion&lt;/a&gt;&lt;/em&gt; data breach because they had a WIFI security vulnerability in one of their stores.  WIFI networks can be extremely insecure and they provide hackers two attack options.  &lt;br /&gt;&lt;h5&gt;Passive Attacks&lt;/h5&gt;Passive attacks are when hackers utilize tools to scan the WIFI network for streams of personal data.  The hacker is hoping an unaware user will enter personal information from a non-secured web site.  For example, &lt;a href="http://www.myspace.com/" target="new"&gt;MySpace&lt;/a&gt; still allows users to log in unsecured (non-https).  &lt;em&gt;Your user credentials will pass the wire in clear text!&lt;/em&gt;  The hacker may attempt to retry those same credentials against your email, corporate, and personal banking sites.  Social networking sites often expose these personal details.  One potential solution is to never re-use your credentials across multiple sites.  Better yet, never enter personal information over an insecure network!&lt;br /&gt;&lt;h5&gt;Active Attacks&lt;/h5&gt;Active attacks are when hackers setup rogue access points on a WIFI network.  From this approach, the hacker is hoping an unsuspecting user connects to their malicious access point.  If a connection is established and the unsuspecting user ignores the security vulnerability warnings, the hacker has access to all your personal data even over a secured (https) site.  &lt;br /&gt;&lt;br /&gt;&lt;h5&gt;Defending WIFI attacks&lt;/h5&gt;&lt;ul&gt;&lt;li&gt;Never enter personal information from insecure (non-https) sites.  Look for either "https" within the browsers URL or look for the locked image icon &lt;img style="border: 0px; margin-bottom:-6px; width: 14px; height: 14px;" src="http://3.bp.blogspot.com/_mO_Jjc1RwAQ/S8B5dgDC9tI/AAAAAAAAAFk/kPuM7UYz_Bs/s400/browser-lock.png" alt="browser lock" /&gt; within your browser to determine if the site is secure.  Browser warnings can also be configured to alert users when they are not on a secured site.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Validate you are connected to a trusted WIFI access point.  Most browsers can protect and alert users of this attack.  For example, from IE you would see a warning shown in &lt;em&gt;Figure 1&lt;/em&gt; below.  However, most users may not completely understand the warning and may ignore it completely.  For example, if you need to board a plane in 15-minutes and need to send an urgent email what do you do?  In IE, the security setting to enable this check is shown in &lt;em&gt;Figure 2&lt;/em&gt; and is enabled by default.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style="border: 1px solid #CCCCCC; width: 400px; height: 148px; valign:top" src="http://1.bp.blogspot.com/_mO_Jjc1RwAQ/S8OqaBb3DiI/AAAAAAAAAFs/VVnih_TB7F0/s400/ie-certificate-warning.png" border="1" alt="Internet Explorer certificate warning" /&gt;&lt;span style="font: 11px/1.4em Arial, sans-serif;"&gt;&lt;br&gt;Figure 1.&lt;/span&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;img style="border: 1px solid #CCCCCC; width: 232px; height: 20px;" src="http://1.bp.blogspot.com/_mO_Jjc1RwAQ/S8OzKlShW8I/AAAAAAAAAF0/aF1oYCagJrY/s400/ie-certificate-setting.png" alt="IE certificate security setting" /&gt;&lt;span style="font: 11px/1.4em Arial, sans-serif;"&gt;&lt;br&gt;Figure 2.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Validate strong encryption is used on your wireless network.  &lt;a href="http://en.wikipedia.org/wiki/Wi-Fi_Protected_Access" target="new"&gt;WPA&lt;/a&gt; is preferred.  For example, if you are still using &lt;a href="http://en.wikipedia.org/wiki/Wired_Equivalent_Privacy" target="new"&gt;WEP&lt;/a&gt; encryption for your home wireless network you should upgrade.  There are tools that allow hackers to crack WEP encryption relatively quickly.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Encrypt sensitive documents.  Encryption adds an additional layer of security.  If you have personal documents saved locally they should be encrypted.  Also, when sending sensitive documents those should be encrypted too.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Stolen Phone&lt;/h3&gt;&lt;br /&gt;The most common type of data breach is from physically stolen devices.  &lt;a href="http://searchsecurity.techtarget.com/news/article/0,289142,sid14_gci1379486,00.html" target="new"&gt;Forty percent&lt;/a&gt; of data breaches fall under this category.  Additionally, hackers may use CSI sticks to extract all data and leave your phone behind.  So do not assume that your data has not been tampered with if you still have your phone in hand.&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;Defending Stolen Phone&lt;/h5&gt;&lt;ul&gt;&lt;li&gt;Encrypt sensitive documents!&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Remotely erase your phone if it is lost or stolen.  For example, &lt;a href="https://www.mobiledefense.com/" target="new"&gt;Mobile Defense&lt;/a&gt; is an Android app that can remotely find, lock, backup, and erase your phone.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Voice Mail Hacking&lt;/h3&gt;&lt;br /&gt;Can you access your mobile voicemail from your cellphone without entering a PIN?  If you can, you may be susceptible to caller ID spoofing.  &lt;em&gt;Make sure a PIN is required for all voicemail access.&lt;/em&gt;  Nitesh Dhanjani has a detailed &lt;a href="http://www.dhanjani.com/blog/2007/07/iphone-users-at.html" target="new"&gt;blog posting&lt;/a&gt; about this attack.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-8303409419005971120?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/8303409419005971120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/04/mobile-security-hacks-to-avoid.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/8303409419005971120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/8303409419005971120'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/04/mobile-security-hacks-to-avoid.html' title='Mobile Security Hacks to Avoid'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_mO_Jjc1RwAQ/S8B5dgDC9tI/AAAAAAAAAFk/kPuM7UYz_Bs/s72-c/browser-lock.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-1545994364898321054</id><published>2010-03-27T07:25:00.012-05:00</published><updated>2010-03-30T17:44:00.555-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Top 5 Home Screen Features For Android Developers</title><content type='html'>&lt;div style='float:right; margin:-55px 0px 0px 0px;'&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://bradbroulik.blogspot.com/2010/03/top-5-home-screen-features-for-android.html';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Top 5 Home Screen Features For Android Developers';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;/div&gt;&lt;br /&gt;Android has several very intriguing components that add many dynamic capabilities to your home screen.  The trend is slowly migrating towards dynamic home screens.  The static screens you have been accustomed to are over.  Users want access to information faster and with fewer clicks.  Patent filings are a very good barometer for the future direction of mobile operating systems and &lt;a href="http://www.tuaw.com/2010/01/14/apple-gets-one-upped-on-homescreen-contact-patent/" target="new"&gt;home screen patents&lt;/a&gt; are one of them.  Dynamic home screens are definitely a trend.  In fact, Android provides many intriguing home screen components that you can leverage right now to create a more efficient and dramatic user experience:&lt;br /&gt; &lt;br /&gt;&lt;h3&gt;App Widgets&lt;/h3&gt;&lt;a href="http://developer.android.com/guide/topics/appwidgets/index.html" target=new&gt;App Widgets&lt;/a&gt; are small application components that you can embed on your home screen.  If you need instant access to important data, these compact portlet-like components are an ideal choice.&lt;br /&gt;Advantages:&lt;ul&gt;&lt;li&gt;Compact design&lt;/li&gt;&lt;li&gt;Provides portlet-like capabilities for your home screen&lt;/li&gt;&lt;li&gt;Quick and simple to access&lt;/li&gt;&lt;li&gt;Refresh frequency is configurable&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Quick Search Box&lt;/h3&gt;&lt;img style="float:right" src="http://1.bp.blogspot.com/_mO_Jjc1RwAQ/S6YlCLAwU8I/AAAAAAAAAFc/96h1ERcjYUI/s400/qsb.png" border="0" alt="Quick search box" id="BLOGGER_PHOTO_ID_5451085118224487362" /&gt;The &lt;a href="http://developer.android.com/resources/articles/qsb.html" target="new"&gt;Quick Search Box&lt;/a&gt; is an extremely powerful feature.  It is the ubiquitous Google search function available directly on your Android device.  In addition to its Google Web search capabilities, users can also search their local device and applications too.  The only caveat with Quick Search is that users must opt-in to search their applications.   &lt;br /&gt;Advantages:&lt;ul&gt;&lt;li&gt;The only search function your device will ever need&lt;/li&gt;&lt;li&gt;Leverages the power of Google Search&lt;/li&gt;&lt;li&gt;Displays results in a consistent framework&lt;/li&gt;&lt;li&gt;Available directly from your home screen&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Live Wallpapers&lt;/h3&gt;&lt;a href="http://developer.android.com/resources/articles/live-wallpapers.html" target="new"&gt;Live Wallpapers&lt;/a&gt; are interactive backgrounds that are available on your home screen.  Most of the current Live Wallpaper apps in this space are of the fun and whimsical type.  However, if you wanted your calendar, appointments, or stock streamer available here it can be accomplished.  &lt;br /&gt;Advantages:&lt;ul&gt;&lt;li&gt;Quick and simple to access&lt;/li&gt;&lt;li&gt;Refresh frequency can be customized&lt;/li&gt;&lt;li&gt;These are simply apps exposed to the background&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Live Folders&lt;/h3&gt;A &lt;a href="http://developer.android.com/resources/articles/live-folders.html" target="new"&gt;Live Folder&lt;/a&gt; is a real-time view of data.  Live Folders can be launched from your home screen via a shortcut.&lt;br /&gt;Advantages:&lt;ul&gt;&lt;li&gt;Quick and simple to access&lt;/li&gt;&lt;li&gt;Data is refreshed in real-time&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Status Bar Notifications&lt;/h3&gt;&lt;a href="http://developer.android.com/guide/topics/ui/notifiers/notifications.html" target="new"&gt;Status Bar Notifications&lt;/a&gt; conveniently alert the user from the home screen.  In addition to an icon or text notification you can also be notified via sound, vibration, or flashing lights. &lt;br /&gt;Advantages:&lt;ul&gt;&lt;li&gt;Quick and simple to access&lt;/li&gt;&lt;li&gt;Alerts can notify users in real-time&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-1545994364898321054?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/1545994364898321054/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/03/top-5-home-screen-features-for-android.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1545994364898321054'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1545994364898321054'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/03/top-5-home-screen-features-for-android.html' title='Top 5 Home Screen Features For Android Developers'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_mO_Jjc1RwAQ/S6YlCLAwU8I/AAAAAAAAAFc/96h1ERcjYUI/s72-c/qsb.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-8400521910425933374</id><published>2010-03-14T23:22:00.004-05:00</published><updated>2010-03-30T17:36:41.271-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conferences'/><title type='text'>No Fluff Just Stuff: Minneapolis Summary (Spring)</title><content type='html'>The &lt;a href="http://www.nofluffjuststuff.com/home/main" target="new"&gt;No Fluff Just Stuff&lt;/a&gt; conference was back in Minneapolis. Here is a brief recap of the sessions I attended: &lt;br /&gt;&lt;br /&gt;&lt;img alt='Friday Sessions' src='http://3.bp.blogspot.com/_mO_Jjc1RwAQ/S52yRNVnWHI/AAAAAAAAAFE/uj9KdHzo7hE/S969-R/2010-03-12.jpg' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Encryption on the JVM: Boot Camp&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Anything can be cracked with &lt;em&gt;time, money, and hardware&lt;/em&gt;.  The goal is to make it an infeasible task.&lt;/li&gt;&lt;li&gt;The Java Cryptography Extention (JCE) within the JDK is a good library.  However, &lt;a href="http://www.jasypt.org/" target="new"&gt;JASYPT&lt;/a&gt; was the speakers preferred encryption library.&lt;/li&gt;&lt;li&gt;Is all of your sensitive information encrypted?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Encryption on the JVM: Advanced Techniques&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;WIFI networks are not secure.  There are plenty of software tools available today that can crack WIFI security algorithms (WEP or WPA).&lt;/li&gt;&lt;li&gt;The unfortunate companies that are exploited for encryption vulnerabilities may appear in the &lt;a href="http://www.nist.org/nist_plugins/content/content.php?content.54" target="new"&gt;Non-Encrypted Hall of Shame&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://cwe.mitre.org/top25/" target="new"&gt;Top 25 most dangerous programming errors&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Hadoop: Divide and Conquer Gigantic Datasets (Intro)&lt;/h3&gt;Key points:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://hadoop.apache.org/mapreduce/" target="new"&gt;Hadoop&lt;/a&gt; is an extremely performant solution for searching enormous amounts (terabytes) of unstructured data (HTML, XML, images).  The performance advantage is achieved from partitioning the search across a cluster of worker nodes.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Keynote: How (not why) Agile Works!&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Agile works for the following three reasons:  &lt;ol&gt;&lt;li&gt;It provides continuous feedback loops&lt;/li&gt;&lt;li&gt;Improves communication&lt;/li&gt;&lt;li&gt;It is fun!&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;img alt='Saturday Sessions' src='http://1.bp.blogspot.com/_mO_Jjc1RwAQ/S52zd4KSA0I/AAAAAAAAAFM/QUHRlowf5Jk/S1600-R/2010-03-13.jpg' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Grails - How to Build Enterprise Apps&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;The GORM capabilities are nice.  It is not necessary to code trivial finder methods.  For example, Person.findAllByAgeLessThan(16) is implicitly available.  The convention works as follows: &lt;Domain_Object&gt;.findAllBy&lt;property&gt;&lt;relational_operator&gt;().  Very convenient.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Implementing Evolutionary Architecture&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Restful Web Services are appealing because they are scalable and free.&lt;/li&gt;&lt;li&gt;What is the value of leveraging Hypermedia as the engine of application state (HATEAOS)?  This strategy completely decouples the server-side workflow from the client.  For example, imagine we have a wizard-style workflow where the user makes decisions and clicks the "next" button as they continue through each step.  As the server processes the requests, it will update the state of the workflow and respond with a list of allowable transitions (URI links) that the user may perform next.  What is the advantage?  If the workflow changes in the future we only have to update the workflow on the server-side.  No client-side changes will be necessary because the server is dynamically driving the UI's navigation by returning the allowable URI links following each request.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Implementing Emergent Design&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;Code == Design&lt;/li&gt;&lt;li&gt;Delay design decisions until the last responsible moment.&lt;/li&gt;&lt;li&gt;Eliminating technical debt must be a continuous process.  You may evaluate your technical debt with &lt;a href="http://sonar.codehaus.org/" target="new"&gt;Sonar&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Code analysis tools: &lt;ul&gt;&lt;li&gt;&lt;a href="http://sourceforge.net/projects/ckjm/" target="new"&gt;ckjm&lt;/a&gt; (analyze coupling)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.eclipse-plugins.info/eclipse/plugin_details.jsp?id=1839" target="new"&gt;x-ray&lt;/a&gt; (Eclipse plug-in to analyze system complexity)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.headwaysoftware.com/products/structure101/index.php" target="new"&gt;Structure101&lt;/a&gt; (Currently used on the Spring framework)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;HTML 5 ... and the Kitchen Sink&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.alistapart.com/articles/previewofhtml5" target="new"&gt;Preview of HTML5&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://html5-now.appspot.com/" target="new"&gt;Supported browsers and features&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://maxheapsize.com/static/html5geolocationdemo.html" target="new"&gt;HTML 5 GeoLocation Demo&lt;/a&gt; &lt;em&gt;(Only works in Firefox)&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://9elements.com/io/projects/html5/canvas/" target="new"&gt;Canvas example&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;img alt='Sunday Sessions' src='http://1.bp.blogspot.com/_mO_Jjc1RwAQ/S520nK9NcvI/AAAAAAAAAFU/9z-k_yznedg/S1600-R/2010-03-14.jpg' /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Architecting Code for Concurrent Execution&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;The preferred design strategy is to manage concurrency concerns at an architectural level.  Traditionally, we have leveraged concurrency via Java's &lt;em&gt;synchronized&lt;/em&gt; keyword at the method level.  Successfully managing concurrency at a low level can become challenging.  Instead, prefer to leverage architectural design patterns to simplify concurrency management.  Several design patterns for consideration include: &lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Producer-consumer_problem" target="new"&gt;Producer-Consumer&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Actor_model" target="new"&gt;Actor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/MapReduce" target="new"&gt;Map/Reduce&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Functional languages are inherently thread-safe because all their objects are immutable.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Introducing Spring Roo&lt;/h3&gt;Key points:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.springsource.org/roo" target="new"&gt;Spring Roo&lt;/a&gt; can help provide Grails-like scaffolding.  A valuable tool for rapid prototyping.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-8400521910425933374?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/8400521910425933374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/03/no-fluff-just-stuff-minneapolis-summary.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/8400521910425933374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/8400521910425933374'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/03/no-fluff-just-stuff-minneapolis-summary.html' title='No Fluff Just Stuff: Minneapolis Summary (Spring)'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_mO_Jjc1RwAQ/S52yRNVnWHI/AAAAAAAAAFE/uj9KdHzo7hE/s72-Rc/2010-03-12.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-1881250796767724702</id><published>2010-02-07T08:12:00.012-06:00</published><updated>2010-02-11T10:21:37.540-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='android'/><title type='text'>Android: Ideal Platform for Busy Java Developers</title><content type='html'>&lt;div style='float:right; margin:-52px 0px 0px 0px;'&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://bradbroulik.blogspot.com/2010/02/android-ideal-platform-for-busy-java.html';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'Android: Ideal Platform for Busy Java Developers';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Android is an appealing technology for Java developers.  The platform provides many new capabilities and possibilities.  In addition, the learning curve is relatively small.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;caption&gt;&lt;strong&gt;Learning Curve Matrix&lt;/strong&gt;&lt;/caption&gt;&lt;tr&gt;&lt;th rowspan="2"&gt;Tool&lt;/th&gt;&lt;th colspan="2" style="text-align:center"&gt;Skillset&lt;/th&gt;&lt;th rowspan="2"&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th style="text-align:center"&gt;New&lt;/th&gt;&lt;th style="text-align:center"&gt;Existing&lt;/th&gt;&lt;/tr&gt;&lt;tr class="alt"&gt;&lt;td&gt;Java&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td style="text-align:center; font-weight:bold; color:green"&gt;X&lt;/td&gt;&lt;td&gt;Android applications are written using the Java programming language.  This should be a major advantage for Android because the Java community is extremely strong.&lt;br/&gt;&lt;br/&gt;A skillset that deserves more attention when developing mobile applications is &lt;em&gt;performance&lt;/em&gt;.  Java developers must adhere to coding practices that optimize performance.  Mobile development is the only platform where production devices will run much slower than your local development environment.  For example, the emulator running on your local PC will have much greater network bandwidth, RAM, and processing power compared to the mobile devices running in production.  Although, within Eclipse you can configure the network speed you want your emulator to simulate.  This is a valuable feature for simulating the speed of your application across different performing mobile networks.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Android SDK&lt;/td&gt;&lt;td style="text-align:center; font-weight:bold; color:red"&gt;X&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;The Android SDK is the only &lt;em&gt;new&lt;/em&gt; skillset that must be acquired for existing Java developers.  The &lt;a href="http://developer.android.com/guide/index.html" target=new&gt;Android developer documentation&lt;/a&gt; is very informative and the &lt;a href="http://developer.android.com/sdk/index.html" target=new&gt;SDK&lt;/a&gt; install has sample applications for nearly every SDK feature.   In addition to learning the SDK, developers will also need to become familiar with the Android architecture, lifecycle, and mobile design guidelines.  Android's developer documentation contains substantial information within each of these areas.&lt;/td&gt;&lt;/tr&gt;&lt;tr class="alt"&gt;&lt;td&gt;IDE&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td style="text-align:center; font-weight:bold; color:green"&gt;X&lt;/td&gt;&lt;td&gt;The preferred IDE for developing Android applications is with Eclipse and the Android Development Tools (ADT) plugin.  Experienced Eclipse developers should have a complete development environment setup in about ten minutes when following the &lt;a href="http://developer.android.com/sdk/index.html" target=new&gt;quick start guide&lt;/a&gt;.  However, &lt;a href="http://developer.android.com/guide/developing/other-ide.html" target=new&gt;other IDE's&lt;/a&gt; are supported for Android development too.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Debugger&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td style="text-align:center; font-weight:bold; color:green"&gt;X&lt;/td&gt;&lt;td&gt;Debugging Android applications is simple.  It is identical to what you have become accustomed to within Eclipse.  Simply set your breakpoints and run your application in Debug mode.&lt;br/&gt;&lt;br/&gt;The &lt;a href="http://developer.android.com/guide/developing/tools/ddms.html" target=new&gt;Dalvik Debug Monitor Server&lt;/a&gt; (DDMS) is an extremely helpful debug tool that's included within the ADT plugin.  It contains features for monitoring threads, CPU usage, memory consumption, and garbage collection.  In addition, it allows the developer to mock incoming calls, SMS messages, location controls (GPS positioning), and network speed and latency.&lt;/td&gt;&lt;/tr&gt;&lt;tr class="alt"&gt;&lt;td&gt;Deploy&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td style="text-align:center; font-weight:bold; color:green"&gt;X&lt;/td&gt;&lt;td&gt;Running your Android application is identical to running a Java application.  Within Eclipse, you simply right-click on your project and select Run As -&gt; Android Application.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Again, the ideal advantage Android has for Java developers is the rapid setup and the productivity of leveraging many existing skills.  Mobile development requires application developers to think in a slightly new paradigm.  Android allows Java developers to focus on this new paradigm exclusively.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Favorite Android Links&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://developer.android.com/index.html" target=new&gt;Android Developer Home&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://googlemobile.blogspot.com/" target=new&gt;Google's Mobile Blog&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.makeuseof.com/tags/google-android/" target=new&gt;Android Articles&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://androidcommunity.com/" target=new&gt;Android Community&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-1881250796767724702?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/1881250796767724702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/02/android-ideal-platform-for-busy-java.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1881250796767724702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1881250796767724702'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/02/android-ideal-platform-for-busy-java.html' title='Android: Ideal Platform for Busy Java Developers'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-4627871641615163112</id><published>2010-01-16T06:40:00.008-06:00</published><updated>2010-04-14T19:21:00.397-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Bulletproof SSO with SAML 2.0</title><content type='html'>Bulletproof status is difficult to achieve.  Even &lt;a href="http://en.wikipedia.org/wiki/Bulletproof_glass" target=new&gt;bulletproof glass&lt;/a&gt; is a myth.  Is it possible to achieve bulletproof status with an SSO implementation?  First, lets start with a code review checklist of assertions that must all pass in order to achieve bulletproof status.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Code Review Checklist for a Web Browser SSO Profile&lt;/h3&gt;&lt;br /&gt;The Web Browser SSO Profile with Redirect/POST bindings is the most common SSO implementation.  The checklist will focus primarily on this profile.  If interested, Google has an extremely helpful &lt;a href="http://code.google.com/apis/apps/sso/saml_static_demo/saml_demo.html" target=new&gt;static demo&lt;/a&gt; and &lt;a href="http://code.google.com/apis/apps/sso/saml_reference_implementation_web.html" target=new&gt;reference implementation&lt;/a&gt; of this SSO profile online.&lt;br /&gt;&lt;h4&gt;Validate Message Confidentiality and Integrity&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;SSL 3.0 is the most common solution to guarantee message confidentiality and integrity.  Refer to &lt;a href="http://docs.oasis-open.org/security/saml/v2.0/saml-sec-consider-2.0-os.pdf" target=new&gt;SAML Security&lt;/a&gt; (section 4) for additional information.  This step will help counter the following attacks:&lt;ul&gt;&lt;li&gt;Eavesdropping 7.1.1.1&lt;/li&gt;&lt;li&gt;Theft of User Authentication Information 7.1.1.2&lt;/li&gt;&lt;li&gt;Theft of the Bearer Token 7.1.1.3&lt;/li&gt;&lt;li&gt;Message Deletion 7.1.1.6&lt;/li&gt;&lt;li&gt;Message Modification 7.1.1.7&lt;/li&gt;&lt;li&gt;Man-in-the-middle 7.1.1.8&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A digitally signed message with a certified key is the most common solution to guarantee message integrity and authentication.  Refer to &lt;a href="http://docs.oasis-open.org/security/saml/v2.0/saml-sec-consider-2.0-os.pdf" target=new&gt;SAML Security&lt;/a&gt; (section 4) for additional information.  This step will help counter the following attacks:&lt;ul&gt;&lt;li&gt;Man-in-the-middle 6.4.2&lt;/li&gt;&lt;li&gt;Forged Assertion 6.4.3&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Validate Protocol Usage&lt;/h4&gt;This is a common area for security gaps.  In fact, &lt;a href="http://code.google.com/apis/apps/sso/saml_reference_implementation_web.html" target=new&gt;Google's original SSO implementation&lt;/a&gt; suffered from a severe &lt;a href="http://www.ai-lab.it/armando/pub/fmse9-armando.pdf" target=new&gt;security flaw&lt;/a&gt; in this area.  The flaw was identified with &lt;a href="http://www.ai-lab.it/satmc/" target=new&gt;SATMC&lt;/a&gt;, a state-of-the-art model checker for security protocols.  Their SSO profile was vulnerable to a Man-in-the-middle attack from a malicious SP (Service Provider).  As ironic as it seems, the SSO Web Browser Profile is most susceptible to attacks from trusted partners. This particular security flaw was exposed because the SAML Response did not contain all of the required data elements necessary for a secure message exchange.  Following the &lt;a href="http://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf" target=new&gt;SAML Profile&lt;/a&gt; usage requirements for AuthnRequest (4.1.4.1) and Response (4.1.4.2) will help counter this attack.  The &lt;a href="http://www.ai-lab.it/armando/pub/fmse9-armando.pdf" target=new&gt;Formal Analysis team&lt;/a&gt; documented these requirements in much simpler notation.  Their documentation for required data elements were as follows: &lt;ul&gt;&lt;li&gt;&lt;strong&gt;AuthnRequest(ID, SP)&lt;/strong&gt;;  An AuthnRequest must contain and ID and SP.  Where ID is a string uniquely identifying the request and an SP identifies the Service Provider that initiated the request.  Furthermore, the request ID attribute must be returned in the response (InResponseTo="&amp;lt;requestId&amp;gt;").  InResponseTo helps guarantee authenticity of the response from the trusted IdP.  This was one of the missing attributes that left Google's SSO vulnerable.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Response(ID, SP, IdP, {AA} K -1/IdP)&lt;/strong&gt;;  A Response must contain all these elements.  Where ID is a string uniquely identifying the response.  SP identifies the recipient of the response. IdP identifies the identity provider authorizing the response. {AA} K -1/IdP is the assertion digitally signed with the private key of the IdP.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;AuthAssert(ID, C, IdP, SP)&lt;/strong&gt;;  An authentication assertion must exist within the Response.  It must contain an ID, a client (C), an identity provider (IdP), and a service provider (SP) identifier.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Validate Protocol Processing Rules&lt;/h4&gt;This is another common area for security gaps simply because of the vast number of steps to assert.  Processing a SAML response is an expensive operation but all steps must be validated.&lt;ul&gt;&lt;li&gt;Validate AuthnRequest processing rules.  Refer to &lt;a href="http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf" target=new&gt;SAML Core&lt;/a&gt; (3.4.1.4) for all AuthnRequest processing rules.  This step will help counter the following attacks:&lt;ul&gt;&lt;li&gt;Man-in-the-middle (6.4.2)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Validate Response processing rules.  Refer to &lt;a href="http://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf" target=new&gt;SAML Profiles&lt;/a&gt; (4.1.4.3) for all Response processing rules.  This step will help counter the following attacks:&lt;ul&gt;&lt;li&gt;Stolen Assertion (6.4.1)&lt;/li&gt;&lt;li&gt;Man-in-the-middle (6.4.2)&lt;/li&gt;&lt;li&gt;Forged Assertion (6.4.3)&lt;/li&gt;&lt;li&gt;Browser State Exposure (6.4.4)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Validate Binding Implementation&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;For an HTTP Redirect Binding refer to &lt;a href="http://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf" target=new&gt;SAML Binding&lt;/a&gt; (3.4).  To view an encoding example, you may want to reference RequestUtil.java found within &lt;a href="http://code.google.com/apis/apps/sso/saml_reference_implementation_web.html" target=new&gt;Google's reference implementation&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;For an HTTP POST Binding refer to &lt;a href="http://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf" target=new&gt;SAML Binding&lt;/a&gt; (3.5).  The caching considerations are also very important.  If a SAML protocol message gets cached, it can subsequently be used as a Stolen Assertion (6.4.1) or Replay (6.4.5) attack.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Validate Security Countermeasures&lt;/h4&gt;Revisit each security threat that exists within the &lt;a href="http://docs.oasis-open.org/security/saml/v2.0/saml-sec-consider-2.0-os.pdf" target=new&gt;SAML Security&lt;/a&gt; document and assert you have applied the appropriate countermeasures for threats that may exist for your particular implementation.  Additional countermeasures considererd should include:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Prefer &lt;em&gt;IP Filtering&lt;/em&gt; when appropriate.  For example, this countermeasure could have prevented Google's initial security flaw if Google provided each trusted partner with a separate endpoint and setup an IP filter for each endpoint.  This step will help counter the following attacks:&lt;ul&gt;&lt;li&gt;Stolen Assertion (6.4.1)&lt;/li&gt;&lt;li&gt;Man-in-the-middle (6.4.2)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Prefer &lt;em&gt;short lifetimes&lt;/em&gt; on the SAML Response.   This step will help counter the following attacks:&lt;ul&gt;&lt;li&gt;Stolen Assertion (6.4.1)&lt;/li&gt;&lt;li&gt;Browser State Exposure (6.4.4)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Prefer &lt;em&gt;OneTimeUse&lt;/em&gt; on the SAML Response. This step will help counter the following attacks:&lt;ul&gt;&lt;li&gt;Browser State Exposure (6.4.4)&lt;/li&gt;&lt;li&gt;Replay (6.4.5)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Need an architectural diagram?  The &lt;a href="http://www.oasis-open.org/committees/download.php/11511/sstc-saml-tech-overview-2.0-draft-03.pdf" target=new&gt;SAML technical overview&lt;/a&gt; contains the most complete diagrams.  For the Web Browser SSO Profile with Redirect/POST bindings refer to the section 4.1.3.  In fact, of all the SAML documentation, the technical overview is the most valuable from a high-level perspective.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-4627871641615163112?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/4627871641615163112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2010/01/bulletproof-sso-with-saml-20.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/4627871641615163112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/4627871641615163112'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2010/01/bulletproof-sso-with-saml-20.html' title='Bulletproof SSO with SAML 2.0'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-2455226926628109385</id><published>2009-11-30T17:15:00.012-06:00</published><updated>2009-12-12T21:58:51.133-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>97 Things Every Project Manager Should Know</title><content type='html'>&lt;div style='float:right; margin:-52px 0px 0px 0px;'&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://bradbroulik.blogspot.com/2009/11/97-things-every-project-manager-should.html';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = '97 Things Every Project Manager Should Know (My Favorite Tips)';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;/div&gt;&lt;br /&gt;I have now finished reading each book within the 97 series:  &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://97-things.near-time.net/wiki/97-things-every-software-architect-should-know-the-book" target="new"&gt;97 Things Every Software Architect Should Know&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/97_Things_Every_Programmer_Should_Know" target=new&gt;97 Things Every Programmer Should Know&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://books.google.com/books?id=SnJFzi7M9XcC&amp;source=gbs_navlinks_s" target=new&gt;97 Things Every Project Manager Should Know&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;br /&gt;&lt;br /&gt;As expected, most topics within this book emphasized the importance of &lt;em&gt;communication&lt;/em&gt; and &lt;em&gt;people&lt;/em&gt;.  &lt;a href="http://www.oreillynet.com/pub/au/3747" target=new&gt;Barbee Davis&lt;/a&gt;, the author of the book also has a 60-minute &lt;a href="http://www.oreillynet.com/pub/e/1446" target=new&gt;Webcast&lt;/a&gt; about this book that you may be interested in if you can not get your hands on the book.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;My Favorite Tips:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://books.google.com/books?id=SnJFzi7M9XcC&amp;printsec=frontcover&amp;source=gbs_v2_summary_r&amp;cad=0#v=onepage&amp;q=&amp;f=false" target=new&gt;Success Is Always Measured in Business Value&lt;/a&gt;&lt;/strong&gt; (Page 36) by &lt;a href="http://www.oreillynet.com/pub/au/3747" target=new&gt;Barbee Davis&lt;/a&gt;&lt;ul&gt;&lt;li&gt;Favorite Quote:&lt;br/&gt;&lt;em&gt;"We need to focus on the fact that the project is only as successful as the business value it adds to the organization."&lt;/em&gt;&lt;br class="clear" /&gt;&lt;br class="clear" /&gt;&lt;/li&gt;&lt;li&gt;Key Message:&lt;br/&gt;It is extremely important that &lt;em&gt;everyone&lt;/em&gt; involved on the project is aware of the business value the project will deliver.  This will clarify the project objective and it allows the team to focus on a single team goal.  Most developers focus on code quality, good design principles, and code maintenance.  While all of those attributes are valuable, none is more important than the business value that your team ultimately delivers for your customer.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://books.google.com/books?id=SnJFzi7M9XcC&amp;printsec=frontcover&amp;source=gbs_v2_summary_r&amp;cad=0#v=onepage&amp;q=&amp;f=false" target=new&gt;Value Results, Not Just Effort&lt;/a&gt;&lt;/strong&gt; (Page 58) by &lt;a href="http://www.agiledeveloper.com/blog/default.aspx" target="new"&gt;Venkat Subramaniam&lt;/a&gt;&lt;ul&gt;&lt;li&gt;Favorite Quote:&lt;br/&gt;&lt;em&gt;"Encourage programmers to report the progress they make, rather than how long they work.  Let them know that you care about getting results rather than keeping track of how long they spent at the computer."&lt;/em&gt;&lt;br class="clear" /&gt;&lt;br class="clear" /&gt;&lt;/li&gt;&lt;li&gt;Key Message:&lt;br/&gt;We typically track effort because it is the simpler of the two metrics to calculate.  The time sheet will show effort.  Alternatively, results will require a calculation of hours worked and velocity.  Ultimately, the focus must be on maximizing velocity and not just effort.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://books.google.com/books?id=SnJFzi7M9XcC&amp;printsec=frontcover&amp;source=gbs_v2_summary_r&amp;cad=0#v=onepage&amp;q=&amp;f=false" target=new&gt;Developer Productivity: Skilled Versus Average&lt;/a&gt;&lt;/strong&gt; (Page 26) by &lt;a href="http://www.nealford.com/" target="new"&gt;Neal Ford&lt;/a&gt;&lt;ul&gt;&lt;li&gt;Favorite Quote:&lt;br/&gt;&lt;em&gt;"Understand that really good software developers are much more productive than average ones.  In fact, some statistics say that really good developers are multiple orders of magnitude better than poor ones."&lt;/em&gt;&lt;br class="clear" /&gt;&lt;br class="clear" /&gt;&lt;/li&gt;&lt;li&gt;Key Message:&lt;br/&gt;Dave Thomas gave a similar talk about &lt;a href="http://www.infoq.com/presentations/Developing-Expertise-Dave-Thomas" target=new&gt;this topic&lt;/a&gt; in 2003.  &lt;em&gt;Continuous learning&lt;/em&gt; is the key point within this post. Combined with the right tools and knowledge you will see greater efficiency gains on your projects.  The real challenge is allocating time to focus on your continuous learning efforts.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://books.google.com/books?id=SnJFzi7M9XcC&amp;printsec=frontcover&amp;source=gbs_v2_summary_r&amp;cad=0#v=onepage&amp;q=&amp;f=false" target=new&gt;Provide Regular Time to Focus&lt;/a&gt;&lt;/strong&gt; (Page 40) by &lt;a href="http://jamesrdf.blogspot.com/" target="new"&gt;James Leigh&lt;/a&gt;&lt;ul&gt;&lt;li&gt;Favorite Quote:&lt;br/&gt;&lt;em&gt;"Typically, a person takes about 20 minutes to regain his train of thought after one of these interruptions.  A 5-minute question actually costs 25 minutes.  Interruptions and recovery time consume 28% of a typical knowledge worker's day."&lt;/em&gt;&lt;br class="clear" /&gt;&lt;br class="clear" /&gt;&lt;/li&gt;&lt;li&gt;Key Message:&lt;br/&gt;Interruptions are not going away.  In fact, actually responding to questions and attending meetings will improve productivity for others within the team.  What's the solution to the interruption problem?  There is no ideal solution to this problem.  However, if you provide good documentation, training, and education, interruptions should be diminished.  If you still find that distractions are an occurrence, try working several hours outside of core hours.  There will be fewer interruptions outside core hours.  While interruptions will not go away, you can configure your daily schedule to find more ideal focus time.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://books.google.com/books?id=SnJFzi7M9XcC&amp;printsec=frontcover&amp;source=gbs_v2_summary_r&amp;cad=0#v=onepage&amp;q=&amp;f=false" target=new&gt;Add Talents, Not Skills, to Your Team&lt;/a&gt;&lt;/strong&gt; (Page 14) by &lt;a href="http://www.menloinnovations.com/founders/sheridanbio.htm" target="new"&gt;Richard Sheridan&lt;/a&gt;&lt;ul&gt;&lt;li&gt;Favorite Quote:&lt;br/&gt;&lt;em&gt;"My advice to anyone seeking to build a strong team is to hire for talents, not for skills.  What talents do I look for when hiring technologists for my development teams?  Good kindergarten skills:"&lt;/em&gt;&lt;br class="clear" /&gt;&lt;br class="clear" /&gt;&lt;/li&gt;&lt;li&gt;Key Message:&lt;br/&gt;This tip changed the way thought about hiring.  I was a believer in tech skills first and team skills second.  Tech skills can be learned relatively quickly.  The same can not always be said about team skills.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-2455226926628109385?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/2455226926628109385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/11/97-things-every-project-manager-should.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/2455226926628109385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/2455226926628109385'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/11/97-things-every-project-manager-should.html' title='97 Things Every Project Manager Should Know'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-348459376579422759</id><published>2009-10-30T07:13:00.025-05:00</published><updated>2009-12-12T21:59:44.117-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>97 Things Every Programmer Should Know</title><content type='html'>&lt;div style='float:right; margin:-52px 0px 0px 0px;'&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://bradbroulik.blogspot.com/2009/10/97-things-every-programmer-should-know.html';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = '97 Things Every Programmer Should Know';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The 97 series now consists of the following titles:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://97-things.near-time.net/wiki/97-things-every-software-architect-should-know-the-book" target="new"&gt;97 Things Every Software Architect Should Know&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/97_Things_Every_Programmer_Should_Know" target=new&gt;97 Things Every Programmer Should Know&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://oreilly.com/catalog/9780596804152" target=new&gt;97 Things Every Project Manager Should Know&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;br /&gt;The &lt;a href="http://bradbroulik.blogspot.com/2009/02/97-things-every-software-architect.html" target="new"&gt;architect book&lt;/a&gt; was very good.  The programming topics were also good but I found more value within the architecture discussions.  I definitely want to get my hands on the project management book soon.  I have a feeling that one will be a bit more humorous.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;My Favorite Things Programmers Should Know:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/The_Professional_Programmer" target=new&gt;The Professional Programmer&lt;/a&gt;&lt;/strong&gt; by &lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/Uncle_Bob" target="new"&gt;Uncle Bob&lt;/a&gt;&lt;ul&gt;&lt;li&gt;Favorite Quote:&lt;br/&gt;&lt;em&gt;"Professionals are responsible. They take responsibility for their own careers. They take responsibility for making sure their code works properly. They take responsibility for the quality of their workmanship. They do not abandon their principles when deadlines loom. Indeed, when the pressure mounts, professionals hold ever tighter to the disciplines they know are right".&lt;/em&gt;&lt;br class="clear" /&gt;&lt;br class="clear" /&gt;&lt;/li&gt;&lt;li&gt;Key Message:&lt;br/&gt;This post was unquestionably at the top of the my list.  The entire message is about &lt;em&gt;personal responsibility&lt;/em&gt;.  This one's a wall hanger.  Print it out, frame it, and hang it up!  This post reminded me of the talk I heard &lt;a href="http://bradbroulik.blogspot.com/2009/01/developing-expertise_27.html" target="new"&gt;Dave Thomas&lt;/a&gt; give many years ago at No Fluff Just Stuff.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/Don%27t_Rely_on_%22Magic_Happens_Here%22" target=new&gt;Don't Rely on "Magic Happens Here"&lt;/a&gt;&lt;/strong&gt; by &lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/AlanGriffiths" target="new"&gt;Alan Griffiths&lt;/a&gt;&lt;ul&gt;&lt;li&gt;Favorite Quote:&lt;br/&gt;&lt;em&gt;"You don't have to understand all the magic that makes your project work, but it doesn't hurt to understand some of it — or to appreciate someone who understands the bits you don't."&lt;/em&gt;&lt;br class="clear" /&gt;&lt;br class="clear" /&gt;&lt;/li&gt;&lt;li&gt;Key Message:&lt;br/&gt; Can you fulfill the roles of every individual on your last project?  Image how valuable you'd be if you could.  Again, the more knowledge you have, the more efficient you and your project will be.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/Hard_Work_Does_not_Pay_off" target=new&gt;Hard Work Does not Pay off&lt;/a&gt;&lt;/strong&gt; by &lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/Olve_Maudal" target="new"&gt;Olve Maudal&lt;/a&gt;&lt;ul&gt;&lt;li&gt;Favorite Quote:&lt;br/&gt;  &lt;em&gt;"programming and software development as a whole involve a continuous learning process."&lt;/em&gt;&lt;br class="clear" /&gt;&lt;br class="clear" /&gt;&lt;/li&gt;&lt;li&gt;Key Message:&lt;br/&gt; &lt;em&gt;Continuous learning&lt;/em&gt; is the key point within this post.  Combined with the right tools and knowledge you will see greater efficiency gains on your projects.  The real challenge is allocating time to focus on your continuous learning efforts.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/First_Write%2C_Second_Copy%2C_Third_Refactor" target=new&gt;First Write, Second Copy, third Refactor&lt;/a&gt;&lt;/strong&gt; by &lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/Mario_Fusco" target="new"&gt;Mario Fusco&lt;/a&gt;&lt;br /&gt; &lt;ul&gt;&lt;li&gt;Favorite Quote:&lt;br/&gt;  &lt;em&gt;"So the first time you are implementing something new, write it in the most readable, plain, and effective way. It is definitely too early to put the general part of your algorithm in an abstract class and move its specialization to the concrete one or to employ any other generalization pattern". &lt;br/&gt;&lt;br /&gt;"The second time you face a problem that resembles the one you solved before, the temptation to refactor that first implementation in order to accommodate both these needs is even stronger. But it may still be too early. It may be a better idea to resist that temptation and do the quickest, safest, and easiest thing it comes you in mind: Copy your first implementation". &lt;br/&gt;&lt;br /&gt;"When you need that solution for the third time, even if to satisfy a slightly different requirement, the time is right to put your brain to work and look for a general solution that elegantly solves all your three problems. Now you are using that algorithm in three different places and for three different purposes, so you can easily isolate its core and make it usable for all three cases".&lt;/em&gt;&lt;br class="clear" /&gt;&lt;br class="clear" /&gt;&lt;/li&gt;&lt;li&gt;Key Message:&lt;br/&gt;The Rule of Three also applies for reuseability.  For example, in order for a solution to be classified as a design pattern the rule of three must apply.  If you can successfully apply the same pattern across three separate systems you have a design pattern.  Furthermore, this rule also applies to API design.  If your API can successfully be consumed by three separate clients, you have a very concrete and proven design.  Applying the Rule of Three for shared services or libraries is also valuable.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;/li&gt;&lt;!-- --&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-348459376579422759?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/348459376579422759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/10/97-things-every-programmer-should-know.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/348459376579422759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/348459376579422759'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/10/97-things-every-programmer-should-know.html' title='97 Things Every Programmer Should Know'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-6924595734329186544</id><published>2009-09-30T18:49:00.002-05:00</published><updated>2009-09-30T18:55:19.734-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>YUI to the rescue</title><content type='html'>Are you still rolling your own HTML user interface components?  If you are, take a look at what &lt;a href="http://developer.yahoo.com/yui/" target="new"&gt;YUI&lt;/a&gt; has to offer.  The advantages of leveraging YUI's standard components are abundant.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;YUI Advantages:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Saves cost on development effort.  The suite of controls are already developed and tested.  This allows your team to work on more valuable tasks.&lt;/li&gt;&lt;li&gt;Excellent performance.  YUI has adopted many of the great performance improvement practices that were identified in &lt;a href="http://developer.yahoo.com/performance/rules.html" target="new"&gt;Best Practices for Speeding Up Your Web Site&lt;/a&gt;.  Several of the performance improvements include:&lt;ul&gt;&lt;li&gt;Minified JavaScript and CSS files.  This will improve page load performance with smaller files to download.&lt;/li&gt;&lt;li&gt;Aggregated or rolled-up JavaScript and CSS files.  This will improve page load performance with fewer HTTP requests.&lt;/li&gt;&lt;li&gt;Yahoo will &lt;a href="http://yuiblog.com/blog/2007/02/22/free-yui-hosting" target="new"&gt;host&lt;/a&gt; the files on their own Content Delivery Network.  In addition, Yahoo will compress and cache all of their controls for even greater performance.  They also manage versioning.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Components are supported across all &lt;a href="http://developer.yahoo.com/yui/articles/gbs/index.html" target="new"&gt;A-Grade browsers&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Helps non-UI experts design beautiful user interfaces.  Yahoo provides the design and CSS layout for all of their components.&lt;/li&gt;&lt;li&gt;&lt;a href="http://bradbroulik.blogspot.com/search/label/accessibility" target="new"&gt;508 compliant&lt;/a&gt;.  All components are screen reader accessible.&lt;/li&gt;&lt;li&gt;All components already have extensive documentation with many examples.&lt;/li&gt;&lt;li&gt;Reusable.  You can apply the YUI controls everywhere because they are not proprietary.&lt;/li&gt;&lt;li&gt;Technology agnostic.  These controls can be applied across all Web environments regardless of technology (Java, .NET, Rails, etc.).&lt;/li&gt;&lt;li&gt;Support many features that allow you to change behavior without customizing the code.&lt;/li&gt;&lt;li&gt;Thier code is clean.  I validated their JavaScript with &lt;a href="http://www.jslint.com" target="new"&gt;JSLint&lt;/a&gt; and few errors were reported.  I also &lt;a href="http://jigsaw.w3.org/css-validator/" target="new"&gt;validated&lt;/a&gt; their CSS files and no major issues existed either.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;YUI Disadvantages:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Some controls are not bullet proof.  For example, there is a sorting issue with their datatable control if you embed the component within a table.  However, this is not an issue if you are working in a &lt;a href="http://bradbroulik.blogspot.com/2009/03/prefer-css-based-designs.html" target="new"&gt;CSS based design&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;They do not have everything but the list is extensive.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Recommendations:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Try to avoid customizations.  Customizing the code will make it difficult to migrate to newer versions in the future.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-6924595734329186544?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/6924595734329186544/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/09/yui-to-rescue.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/6924595734329186544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/6924595734329186544'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/09/yui-to-rescue.html' title='YUI to the rescue'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-3221031620072784920</id><published>2009-08-31T21:36:00.003-05:00</published><updated>2009-08-31T21:40:19.954-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Preventing Buffer Overflow Attacks</title><content type='html'>Is your website resilient enough to withstand a &lt;a href="http://en.wikipedia.org/wiki/Buffer_overflow" target="new"&gt;buffer overflow&lt;/a&gt; attack?  A buffer overflow attack is actually one of the simpler attacks a malicious user may attempt.  Imagine the following scenario.  You have a public facing web page that allows unauthorized users to submit data.  A malicious user probes your site to see if you have exposed this vulnerability.  If your site is at risk, it may only take minutes for the user to bring your site down if they employ a &lt;a href="http://en.wikipedia.org/wiki/Botnet" target="new"&gt;botnet&lt;/a&gt; attack.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Attack&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;The simplest attack method is for malicious users to throw overloading (2GB - 8GB) amounts of data in a text field in hopes of crashing the server due to out of memory errors.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;The Prevention&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Bounds checking on the server-side is the most effective solution for preventing buffer overflows.  For example, if you are using Spring's annotation-based validation this is all you would need:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/**&lt;br /&gt; *&lt;br /&gt; * &lt;span class="code-highlight1"&gt;&lt;a href="https://springmodules.dev.java.net/docs/reference/0.8/html_single/#d0e9699" target="new"&gt;Spring's annotation reference documentation&lt;/a&gt;&lt;/span&gt;&lt;br /&gt; * &lt;span class="code-highlight1"&gt;&lt;a href="http://wheelersoftware.com/articles/spring-bean-validation-framework.html" target="new"&gt;Configuration setup example&lt;/a&gt;&lt;/span&gt;&lt;br /&gt; */&lt;br /&gt;public class Student {&lt;br /&gt; &lt;br /&gt; @NotBlank&lt;br /&gt; @Length(max = 50) &lt;br /&gt; private String firstName;&lt;br /&gt; &lt;br /&gt; @Length(min = 1, max = 50) &lt;br /&gt; private String lastName;&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;HTML's maxlength attribute is &lt;em&gt;NOT&lt;/em&gt; sufficient:&lt;pre&gt;&amp;lt;input type="text" name="firstName" maxlength="50" /&amp;gt;&lt;/pre&gt;  This is not secure because there are &lt;a href="http://bradbroulik.blogspot.com/2009/03/identify-security-gaps-with-tamper-data.html" target="new"&gt;tools&lt;/a&gt; that will enable users to bypass this HTML tier of validation.  You must perform max length validation on the server-side as in the example above.&lt;/li&gt;&lt;li&gt;Leverage the bulkhead stability pattern to decouple your authenticated business critical applications from your publicly exposed (more vulnerable) applications.  The goal of this pattern is to preserve the stability for a particular group of customers.  Most software attacks are targeted at publicly available web sites.  You should leverage this pattern if you want to help preserve the stability of your authenticated users during an attack on your publicly available sites.&lt;li&gt;Prefer to keep public data out of session.  This simple solution will help preserve memory if a user attempts a buffer overflow attack.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-3221031620072784920?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/3221031620072784920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/08/preventing-buffer-overflow-attacks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3221031620072784920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3221031620072784920'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/08/preventing-buffer-overflow-attacks.html' title='Preventing Buffer Overflow Attacks'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-3179233063796851226</id><published>2009-07-31T20:00:00.029-05:00</published><updated>2009-07-31T21:17:23.799-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><title type='text'>JavaScript Singletons</title><content type='html'>JavaScript singletons are relatively simple to create.  With two additional characters you can define your object as a &lt;a href="http://en.wikipedia.org/wiki/Singleton_pattern"&gt;singleton&lt;/a&gt;.  I'll show how this is accomplished in a moment.  In my prior &lt;a href="http://bradbroulik.blogspot.com/2009/05/javascript-good-parts.html"&gt;JavaScript post&lt;/a&gt; I talked about why the module pattern was preferred for creating objects.  Those objects were prototype-based and multiple instances were allowed.  The following examples illustrate the preferred way to create singletons with the Module pattern.  This should be your preferred creational pattern for creating JavaScript singletons.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Singleton Pattern Example #1:&lt;/h4&gt;&lt;pre&gt;&lt;span class="code-highlight1"&gt;/*&lt;br /&gt; * Singleton counter example.&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;var mySingletonCounter = function() {&lt;br /&gt; &lt;br /&gt;   &lt;span class="code-highlight1"&gt;/* private, static variables */&lt;/span&gt;&lt;br /&gt;   var count = 0;&lt;br /&gt;&lt;br /&gt;   return {&lt;br /&gt;      &lt;span class="code-highlight1"&gt;/* public methods */&lt;/span&gt;&lt;br /&gt;      increment: function (inc) {&lt;br /&gt;           alert('Adding ' + inc + ' to count.');&lt;br /&gt;           count += inc;&lt;br /&gt;      },&lt;br /&gt; &lt;br /&gt;      getCount: function() {&lt;br /&gt;           alert('The current count is ' + count);&lt;br /&gt;           return count;&lt;br /&gt;      }&lt;br /&gt;   };&lt;br /&gt;}&lt;strong&gt;()&lt;/strong&gt;; &lt;span class="code-highlight1"&gt;// &lt;- These two parentheses define the object as a singleton.  It assigns the result of invoking this function to mySingletonCounter.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;To exercise the singleton, the button below will execute the following code:&lt;br /&gt;&lt;pre&gt;mySingletonCounter.increment(2); mySingletonCounter.getCount();&lt;/pre&gt;&lt;a href="javascript:mySingletonCounter.increment(2); mySingletonCounter.getCount();" class="button"&gt;Run Singleton Counter&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Singleton Pattern Example #2:&lt;/h4&gt;&lt;pre&gt;&lt;span class="code-highlight1"&gt;/*&lt;br /&gt; * Singleton data access example.&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;var mySingletonData = function() {&lt;br /&gt; &lt;br /&gt;   &lt;span class="code-highlight1"&gt;/* private, static variables */&lt;/span&gt;&lt;br /&gt;   var data = {&lt;br /&gt;       1: "Harry Potter and the Philosopher's Stone",&lt;br /&gt;       2: "Harry Potter and the Chamber of Secrets",&lt;br /&gt;       3: "Harry Potter and the Prisoner of Azkaban"&lt;br /&gt;   };&lt;br /&gt;&lt;br /&gt;   return {&lt;br /&gt;      &lt;span class="code-highlight1"&gt;/* public methods */&lt;/span&gt;&lt;br /&gt;      getData: function() {&lt;br /&gt;           return data;&lt;br /&gt;      }&lt;br /&gt;   };&lt;br /&gt;}();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Reference the singleton object in the following manner:&lt;br /&gt;&lt;pre&gt;mySingletonData.getData()[2];&lt;/pre&gt;&lt;a class="button" href="javascript:alert(mySingletonData.getData()[2]);"&gt;Run Singleton Data&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Advantages:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;It is extremely simple to declare a JavaScript object as a singleton.  More dynamic languages are focusing on simplicity.  For example, Groovy has recently provided the &lt;a href="http://groovy.codehaus.org/Singleton+transformation"&gt;@Singleton transformation&lt;/a&gt; to simplify Singleton creation.&lt;/li&gt;&lt;li&gt;Improved run-time performance vs the prototype-based creational pattern.&lt;/li&gt;&lt;li&gt;You still leverage all the advantages that the &lt;a href="http://bradbroulik.blogspot.com/2009/05/javascript-good-parts.html#advantages"&gt;module pattern&lt;/a&gt; provides.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-3179233063796851226?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/3179233063796851226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/07/javascript-singletons_31.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3179233063796851226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3179233063796851226'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/07/javascript-singletons_31.html' title='JavaScript Singletons'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-8146924464763037640</id><published>2009-06-27T10:02:00.019-05:00</published><updated>2010-03-14T23:19:48.341-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Agile: A requirements change is a competitive advantage</title><content type='html'>At what point in the lifecycle should requirements be locked down?  &lt;br /&gt;&lt;ol&gt;&lt;li&gt;Before development begins&lt;/li&gt;&lt;li&gt;Never&lt;/li&gt;&lt;li&gt;Somewhere in between&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Most developers will immediately choose "Before development begins" for simplicity.  However, if you work in an agile environment that responds well to change then there are many advantages to "Never".  &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Advantages of Changing Requirements&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Changing requirements will improve the product and should give you a competitive advantage.&lt;/li&gt;&lt;li&gt;Changing requirements will evaluate the efficiencies of your development, QA, and deployment processes.  Highly effective or agile teams will deliver the new requirement relatively pain-free.&lt;/li&gt;&lt;li&gt;Changing requirements encourage automation throughout the lifecycle.  The important factor here is that it encourages automation across all departments (development, QA, deployment).  The following attributes must exist within each department for this strategy to be successful:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Development:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Automated JUnit tests - frequent changes must be tested efficiently.&lt;/li&gt;&lt;li&gt;Continuous Integration - frequent changes require stable environments.&lt;/li&gt;&lt;li&gt;Code reviews - This knowledge transfer session will give your team the flexibility of having anyone work any task more efficiently.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;QA:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Automated regression tests - frequent changes must be tested efficiently.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;Deployment:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Automated deployment scripts - simplify and more accurately deploy the changed release modules.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Software must be delivered faster so the customer's can identify the change points sooner in the lifecycle.  The goal is to deliver testable software quicker.  How many of you deliver testable code after iteration one?  How many of you have customer demos of working software after iteration one?  The goal is to identify changes sooner in the lifecycle and this will help minimize the risk of failing to meet your production delivery date.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Disadvantages of Changing Requirements&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Changing requirements may delay the project.  This is where the debate typically begins.  However, if you initially plan for some percentage of change you should be fine.  Identifying change early in the lifecycle will also help remedy the impact.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;The Hybrid Example&lt;/h4&gt;Which auto makers were most successful with their hybrid initiatives?  It was the automakers that adopted lean/agile practices many years ago.  The automakers that did not change soon enough are now scrambling to recover.  Changing requirements can have a huge competitive advantage if your environment responds well to change.  &lt;em&gt;A key attribute of being agile is adapting to change.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-8146924464763037640?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/8146924464763037640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/06/agile-requirements-change-is.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/8146924464763037640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/8146924464763037640'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/06/agile-requirements-change-is.html' title='Agile: A requirements change is a competitive advantage'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-7083037138634600799</id><published>2009-05-07T21:12:00.031-05:00</published><updated>2009-12-12T22:00:09.095-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>JavaScript: The Good Parts</title><content type='html'>&lt;div style='float:right; margin:-52px 0px 0px 0px;'&gt;&lt;script type="text/javascript"&gt;var dzone_url = 'http://bradbroulik.blogspot.com/2009/05/javascript-good-parts.html';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_title = 'JavaScript: The Good Parts ';&lt;/script&gt;&lt;script type="text/javascript"&gt;var dzone_style = '2';&lt;/script&gt;&lt;script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"&gt;&lt;/script&gt;&lt;/div&gt;&lt;br /&gt;What's the most popular functional language?  &lt;em&gt;JavaScript&lt;/em&gt; is.  And if you are interested in learning the finer points of the language I recommend Douglas Crockford's latest book titled &lt;a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742" target="new"&gt;JavaScript: The Good Parts&lt;/a&gt;.  It is a very quick read at only 145 pages!  The most valuable lesson I learned from the book was the &lt;em&gt;correct&lt;/em&gt; way to create JavaScript objects with the Module Pattern.  The following examples illustrate the Module pattern.  This creational pattern leverages closure to achieve encapsulation, information hiding, and global safety.  No other JavaScript creational pattern provides these capabilities.  This should be your preferred creational pattern in JavaScript.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Module Pattern Examples:&lt;/h4&gt;&lt;pre&gt;&lt;span class="code-highlight1"&gt;/**&lt;br /&gt; * A search module that provides the ability to search by name.&lt;br /&gt; */&lt;/span&gt;&lt;br /&gt;var search = function (criteria) {&lt;br /&gt;    &lt;span class="code-highlight1"&gt;/* private variables */&lt;/span&gt;&lt;br /&gt;    var name = criteria.name;&lt;br /&gt; &lt;br /&gt;    &lt;span class="code-highlight1"&gt;/* private methods */&lt;/span&gt;&lt;br /&gt;    var renderResponse = function() {&lt;br /&gt;        alert('rendering response for: ' + name);&lt;br /&gt;    };&lt;br /&gt; &lt;br /&gt;    &lt;span class="code-highlight1"&gt;/* return our public API methods */&lt;/span&gt;&lt;br /&gt;    return {&lt;br /&gt;        execute: function() {&lt;br /&gt;            alert('searching for: ' + name);  &lt;span class="code-highlight1"&gt;// Perform an AJAX search&lt;/span&gt;&lt;br /&gt;            renderResponse();                    &lt;span class="code-highlight1"&gt;// Perform renderResponse as part of the AJAX callback.&lt;/span&gt;&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;};&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Instantiate a new search object:&lt;br /&gt;&lt;pre&gt;search({'name':'Johnny'}).execute();&lt;/pre&gt;&lt;p&gt;&lt;a class="button" href="javascript:search1({'name':'Johnny'}).execute();"&gt;Run search example&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Alternatively, if you prefer to return your public API methods via assignment you may find this example to be simpler:&lt;/p&gt;&lt;pre&gt;var search = function (criteria) {&lt;br /&gt;    &lt;span class="code-highlight1"&gt;/* private variables */&lt;/span&gt;&lt;br /&gt;    var that = {};&lt;br /&gt;    var name = criteria.name;&lt;br /&gt; &lt;br /&gt;    &lt;span class="code-highlight1"&gt;/* private methods */&lt;/span&gt;&lt;br /&gt;    var renderResponse = function() {&lt;br /&gt;        alert('rendering response for: ' + name);&lt;br /&gt;    };&lt;br /&gt; &lt;br /&gt;    &lt;span class="code-highlight1"&gt;/* Assign public API methods to that. */&lt;/span&gt;&lt;br /&gt;    that.execute = function () {&lt;br /&gt;        alert('searching for: ' + name); &lt;span class="code-highlight1"&gt;// Perform an AJAX search&lt;/span&gt;&lt;br /&gt;        renderResponse();                   &lt;span class="code-highlight1"&gt;// Perform renderResponse as part of the AJAX callback.&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    return that;  &lt;span class="code-highlight1"&gt;// return by assignment example.&lt;/span&gt;&lt;br /&gt;};&lt;/pre&gt;&lt;br /&gt;&lt;a name="advantages"&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4&gt;Module Pattern Advantages&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Improved encapsulation. For example, if the renderResponse functionality is only pertinent to search, we can encapsulate that behavior within the search object.&lt;/li&gt;&lt;li&gt;Better information hiding.  No consumers of the search module will be able to call renderResponse directly because it is private.&lt;/li&gt;&lt;li&gt;The objects are global-safe.  You will not see any references to the &lt;strong&gt;this&lt;/strong&gt; keyword anywhere.  This will eliminate any possibility of altering global variables.&lt;/li&gt;&lt;li&gt;Requires less effort than other creational patterns (pseudoclassical pattern, Object.create pattern).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;JavaScript Resources:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;JavaScript: The Good Parts &lt;a href="http://google-code-updates.blogspot.com/2009/03/doug-crockford-javascript-good-parts.html" target="new"&gt;presentation&lt;/a&gt; from the Google Code Blog.&lt;/li&gt;&lt;li&gt;In particular, I found the following sections within &lt;a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742" target="new"&gt;JavaScript: The Good Parts&lt;/a&gt; to be most valuable for me.  These mere ten pages of content were worth the cost of the book!:&lt;ul&gt;&lt;li&gt;Chapter 4 (Functions):&lt;ul&gt;&lt;li&gt;Closure&lt;/li&gt;&lt;li&gt;Module&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Chapter 5 (Inheritance): &lt;ul&gt;&lt;li&gt;Functional&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href="http://www.jslint.com" target="new"&gt;JSLint&lt;/a&gt;: an excellent tool for code quality analysis.&lt;/li&gt;&lt;li&gt;Doug Crockford has at least eight JavaScript presentations available at &lt;a href="http://developer.yahoo.com/yui/theater/" target="new"&gt;YUI theatre&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;script&gt;&lt;br /&gt;var search1 = function (criteria) {&lt;br /&gt;    /* private variables */&lt;br /&gt;    var name = criteria.name;&lt;br /&gt; &lt;br /&gt;    /* private methods */&lt;br /&gt; var renderResponse = function() {&lt;br /&gt;     alert('rendering response for: ' + name);&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    /* return our public API methods */&lt;br /&gt;    return {&lt;br /&gt;     execute: function() {&lt;br /&gt;      alert('searching for: ' + name);  // Perform an AJAX search&lt;br /&gt;      renderResponse();    // Perform renderResponse as part of the AJAX callback.&lt;br /&gt;     }&lt;br /&gt;    };&lt;br /&gt;};&lt;br /&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-7083037138634600799?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/7083037138634600799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/05/javascript-good-parts.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/7083037138634600799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/7083037138634600799'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/05/javascript-good-parts.html' title='JavaScript: The Good Parts'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-8775251082334393336</id><published>2009-04-20T21:47:00.006-05:00</published><updated>2009-04-27T20:09:27.376-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Kanban: The Good Parts</title><content type='html'>&lt;h3&gt;Kanban Estimates&lt;/h3&gt;Struggling with those developer estimates?  If you are, you may want to give Kanban's estimation practice a try.  The Kanban methodology almost entirely eliminates the estimation process.  Instead of using formal planning and estimation all features have approximately the same size.  Hours that were previously burnt estimating are actually spent delivering software. When compared to the Scrum estimation model, this style of estimation is very lean.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;Hours previously spent estimating are spent delivering software.&lt;/li&gt;&lt;li&gt;The focus is on delivering software more rapidly vs focusing on when the software will be delivered.&lt;/li&gt;&lt;li&gt;Does not invest heavily in a metric that is not scientific or always accurate.&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;High level estimates are still necessary for resource planning.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Kanban Stand ups&lt;/h3&gt;Unlike Scrum stand ups where each individual answers the three magical questions of: what did I do yesterday, what am I doing today, and what issues do I have.  Kanban focuses exclusively on issues.  For example, the global question now becomes: Does anyone have any issues?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;Quicker stand ups.&lt;/li&gt;&lt;li&gt;The stand up scales better for larger teams.&lt;/li&gt;&lt;li&gt;Issues are the main focus.&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;May lose visibility of what each member is working on.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;Resources&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.infoq.com/news/2008/10/kanban_agile" target="_new"&gt;Kanban as Alternative Agile Implementation&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.infoq.com/presentations/kanban-for-software" target="_blank"&gt;A Kanban System for Software Engineering&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-8775251082334393336?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/8775251082334393336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/04/kanban-good-parts.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/8775251082334393336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/8775251082334393336'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/04/kanban-good-parts.html' title='Kanban: The Good Parts'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-4666499922020787826</id><published>2009-04-06T20:30:00.007-05:00</published><updated>2009-04-06T20:48:17.606-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Secure Computing: Preventing Cross Site Scripting (XSS)</title><content type='html'>&lt;h3&gt;XSS prevention cheat sheet&lt;/h3&gt;The best strategies for preventing Cross Site Scripting can be found in OWASP's &lt;a href="http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet"&gt;XSS prevention cheat sheet&lt;/a&gt;.  Several important notes include:&lt;ul&gt;&lt;li&gt;&lt;i&gt;You MUST use the escape syntax for the part of the HTML document you're putting untrusted data into.&lt;/i&gt;  There is no single escape function that can be applied for all output contexts (HTML, CSS, JavaScript).  &lt;a href="http://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API"&gt;ESAPI&lt;/a&gt; has an API that provides encoding rules for a particular output context.  Refer to the OWASP's &lt;a href="http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#XSS_Prevention_Rules"&gt;prevention rules&lt;/a&gt; for more details.&lt;/li&gt;&lt;li&gt;&lt;i&gt;It is impossible to secure a JavaScript context with escaping.&lt;/i&gt;  This is an important note because there is no defense to this scenario except to eliminate the output of dynamic content within your JavaScript context entirely.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3&gt;XSS and JSTL&lt;/h3&gt;JSTL used appropriately will protect you from an XSS attack within your HTML context.  For example, this a valid JSTL solution:&lt;/li&gt;&lt;pre&gt;&lt;span class="code-highlight1"&gt;&amp;lt;%-- XSS safe --%&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;lt;c:out value="${untrusted_data}" escapeXml="true" /&amp;gt;&lt;/pre&gt;  By default, the excapeXml attribute is "true" within the out tag so you don't have to explicitly declare it.&lt;br /&gt;   &lt;br /&gt;The JSTL expression language alone will &lt;em&gt;NOT&lt;/em&gt; protect you from an XSS attack.  For example this is not safe and &lt;em&gt;MUST&lt;/em&gt; be avoided for all untrusted data:&lt;pre&gt;&lt;span class="code-highlight1" style="color:red;"&gt;&amp;lt;%-- Not XSS safe --%&amp;gt;&lt;/span&gt;&lt;br /&gt;${untrusted_data}&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;XSS input validation&lt;/h3&gt;Validating input characters for malicious data should not be your only method of prevention.  It is recommended to always escape untrusted data on the output side because you account for all data regardless of where the data originated from.  Maybe the data was maliciously altered in the database or perhaps your third-party vendor sent harmful data outside HTTP.  Input validation does not account for those scenarios and should not be used as your only defense.  Output escaping with ESAPI or JSTL covers all bases regardless of where the data originated from.  If you prefer to validate user input for XSS you may use regular expressions. A whitelist strategy of allowing positive characters is preferred.  For example, the regular expression code below is a whitelist pattern that only allows certain characters as valid input:&lt;br /&gt;&lt;pre&gt;public final class ValidationUtils {&lt;br /&gt;&lt;br /&gt; &lt;span class="code-highlight1"&gt;    /* Whitelist validation example.  Only allow alphanumerics and special characters: -@&amp;., */&lt;/span&gt;&lt;br /&gt;    public final static Pattern VALID_TEXT_FIELD_PATTERN = Pattern.compile("[A-Za-z0-9-@&amp;\\.,\\s]*");&lt;br /&gt; &lt;br /&gt;    public static final boolean isValid(Pattern pattern, final String value) {&lt;br /&gt;        return pattern.matcher(value).matches();&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;XSS and JSON&lt;/h3&gt;If you are using JSON on the client-side make sure you also validate your JSON content for malicious data.  Douglas Crockford, in his recent book &lt;a href="http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742"&gt;JavaScript: The Good Parts&lt;/a&gt; recommends using JSON.parse() for all untrusted content.  JSON.parse() will throw an exception if the text contains anything dangerous.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-4666499922020787826?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/4666499922020787826/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/04/secure-computing-preventing-cross-site.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/4666499922020787826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/4666499922020787826'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/04/secure-computing-preventing-cross-site.html' title='Secure Computing: Preventing Cross Site Scripting (XSS)'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-3279267902071925959</id><published>2009-03-26T20:18:00.005-05:00</published><updated>2009-04-01T17:20:39.088-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>Identify security gaps with Tamper Data</title><content type='html'>How secure is your application?  Why not perform a security audit yourself.  &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/966"&gt;Tamper Data&lt;/a&gt; is a very helpful Firefox tool to help identify security gaps your applications may have.  Do you really think your hidden form fields are safe?  Do you think your select list data can't be altered?  Basically, all data exposed to the browser context can be altered by the end user.  &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Advantages of Tamper Data&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Tamper data will show you how easy your data can be attacked.  Every post parameter can be altered.  This includes hidden fields and select list values.&lt;/li&gt;&lt;li&gt;Tamper data helps emphasize the data you must secure from a malicious user.  Are you exposing any identifier values within the browser context?  Look for these primary key values.  You may find these in edit or search result screens.  If you do expose sensitive keys, a malicious user may alter them as they search for sensitive data.&lt;/li&gt;&lt;li&gt;Tamper data makes it very easy for developers to quickly test your application against cross site scripting (XSS) and SQL injection attacks.&lt;/li&gt;&lt;li&gt;QA can leverage Tamper Data to identify security gaps also.  This is a practice that is not very common.  Tamper Data can simplify this effort.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How to setup Tamper Data&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;From within Firefox, download: &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/966"&gt;Tamper Data&lt;/a&gt;.&lt;br /&gt;&lt;li&gt;After the download is complete, you may access the Tamper Data screen from either the Tools menu or View menu:&lt;br /&gt; &lt;br /&gt;&lt;div style="width:100%; overflow:auto"&gt;&lt;img style="float:left; border-width:1px; border-color: black; border-style:solid;" src="http://2.bp.blogspot.com/_mO_Jjc1RwAQ/ScF69gpg4BI/AAAAAAAAACA/bNUi9BEhJh0/s400/tools-menu.jpg" border="1" width="215" height="288" alt="Accessing tamper data from tools menu" /&gt; &lt;img style="float:left;border-width:1px; border-color: black; border-style:solid; margin-left:10px;" src="http://1.bp.blogspot.com/_mO_Jjc1RwAQ/ScF-LxuWv6I/AAAAAAAAACI/nH-DHfjByyI/s400/view-menu.jpg" width="315" height="162" border="1" alt="Accessing Tamper data from view menu, side bar sub menu" /&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;Start Tamper data by clicking the "Start Tamper" button:  &lt;img style="float:left; border-width:1px; border-color: black; border-style:solid;" src="http://1.bp.blogspot.com/_mO_Jjc1RwAQ/ScL6W5ElOUI/AAAAAAAAACQ/i24pczWs6Ho/s400/start-tamper.jpg" width="215" height="57" border="0" alt="start tamper button" /&gt;&lt;/li&gt;&lt;li&gt;&lt;br class="clear"/&gt;&lt;br /&gt;You can now test your application for any gaps.  You may tamper with any post parameter values that appear in the right pane:&lt;img style="border-width:1px; border-color: black; border-style:solid;" src="http://2.bp.blogspot.com/_mO_Jjc1RwAQ/ScMA6mOSqqI/AAAAAAAAADA/aID3tXX289w/s400/post-params.jpg" width="400" height="101" border="0" alt="tamper screen shot" /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Alright, so what are a few strategies for securing our data?  In my next post I will discuss a few defensive programming practices to help secure your sensitive data.  I'll also expose a JSTL gap that makes you vulnerable to XSS attacks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-3279267902071925959?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/3279267902071925959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/03/identify-security-gaps-with-tamper-data.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3279267902071925959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3279267902071925959'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/03/identify-security-gaps-with-tamper-data.html' title='Identify security gaps with Tamper Data'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_mO_Jjc1RwAQ/ScF69gpg4BI/AAAAAAAAACA/bNUi9BEhJh0/s72-c/tools-menu.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-6519530364492868267</id><published>2009-03-12T21:26:00.003-05:00</published><updated>2009-03-12T21:31:08.328-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Prefer CSS-based designs</title><content type='html'>Are you leveraging the full potential of CSS?  Traditionally, tabled-based layouts were the standard for structuring content.  CSS provides many advantages that we should be leveraging today.  In short, table-based designs should forever be deprecated.  &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Advantages for adopting CSS-based designs:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;CSS-based designs render content better in mobile-based browsers.  With mobile apps on the rise it is becoming even more important to apply CSS-based designs today on your regular browser applications.  Sites designed with CSS layouts offer much better flexibility in regards to how the content is rendered on the UI.  For example, given the same content you may apply a different style for your mobile based application vs your non-mobile based application.&lt;/li&gt;&lt;li&gt;Your pages will have less code and become much easier to read.  No more &amp;lt;table&amp;gt;, &amp;lt;tr&amp;gt;, and &amp;lt;td&amp;gt; tags to clutter your content!&lt;/li&gt;&lt;li&gt;With less code to maintain, refactoring becomes simpler.&lt;/li&gt;&lt;li&gt;Your UI becomes more &lt;a href="http://bradbroulik.blogspot.com/2009/02/designing-for-accessibility.html"&gt;accessible&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Lightweight pages will be more performant.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;CSS Books:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/CSS-Mastery-Advanced-Standards-Solutions/dp/1590596145/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1236430931&amp;sr=1-1"&gt;CSS Mastery&lt;/a&gt;:  &lt;ul&gt;&lt;li&gt;This book was the most valuable for me.  It's a quick read and their &lt;a href="http://www.friendsofed.com/download.html?isbn=1590596145"&gt;examples&lt;/a&gt; are very good.  I typically reference their examples first when looking for solutions.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/CSS-Missing-Manual-David-McFarland/dp/0596526873/ref=sr_1_2?ie=UTF8&amp;s=books&amp;qid=1236430931&amp;sr=1-2"&gt;CSS The missing manual&lt;/a&gt;:  &lt;ul&gt;&lt;li&gt;This is also a valuable book.  This book contains much more content than the prior book and may be targeted for a more introductory audience.  Their &lt;a href="http://www.sawmac.com/missing/css/tutorials/"&gt;examples&lt;/a&gt; are also good but I typically reference the CSS Mastery examples first.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;CSS Tools:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://getfirebug.com/"&gt;FireBug&lt;/a&gt;:&lt;ul&gt;&lt;li&gt;Arguably the best tool ever invented for Web development.  Refer to the FireBug site for their CSS support features.  Simply awesome for everything (debugging, JavaScript, CSS)!   &lt;a href="http://developer.yahoo.com/yslow/"&gt;YSlow&lt;/a&gt; is also a helpful FireBug addition that provides an excellent performance report card.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/grids/"&gt;YUI Grids CSS&lt;/a&gt;:&lt;ul&gt;&lt;li&gt;If you are looking for a CSS framework then this may be of value.  Their base and grid styles should help with layout while their reset style will help get all browser's on an even playing field.  Yahoo has a good &lt;a href="http://developer.yahoo.com/yui/grids/"&gt;demo&lt;/a&gt; of its features on their YUI Grids home page.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-6519530364492868267?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/6519530364492868267/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/03/prefer-css-based-designs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/6519530364492868267'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/6519530364492868267'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/03/prefer-css-based-designs.html' title='Prefer CSS-based designs'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-696192315842480408</id><published>2009-02-28T08:11:00.019-06:00</published><updated>2009-03-12T22:20:46.269-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><title type='text'>Spring Webflow: An elegant DSL for your MVC</title><content type='html'>&lt;span style="font-family:arial;"&gt;&lt;a href="http://www.springsource.org/webflow"&gt;Spring Web Flow&lt;/a&gt; is an interesting MVC framework.  Under the hood, it is an implementation of a &lt;a href="http://en.wikipedia.org/wiki/Finite_state_machine"&gt;Finite State Machine (FSM)&lt;/a&gt;. However, the beauty of Spring Web Flow is in the simplified DSL templating that Web Flow provides.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;First, lets look at a simple example:&lt;span&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;flow start-state="start"&amp;gt;&lt;br /&gt; &lt;br /&gt;    &amp;lt;view-state id="start" view="chooseColor.jsp"&amp;gt;&lt;br /&gt;        &amp;lt;transition on="red" to="showRed" /&amp;gt;&lt;br /&gt;    &amp;lt;/view-state&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;end-state id="showRed" view="red.jsp"/&amp;gt;&lt;br /&gt; &lt;br /&gt;&amp;lt;/flow&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This web flow above has two states and one transition.  States in web flow typically correspond to views.  In this case, my views are JSP's.  Transitions will be triggered based on events.  Within a JSP, events correspond to buttons or links.  The event or button to trigger the red event is defined here:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Verdana, Arial, helvetica, sans-serif; border: 1px solid #CCCCCC; padding: 5px; overflow: auto; background-color: #f3f5e9; font-size: 12px; line-height: 14px;&lt;br /&gt;width: 100%;"&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;br /&gt; ... &lt;br /&gt;  &lt;br /&gt;  &amp;lt;form:form action="${flowExecutionUrl}"&amp;gt;&lt;br /&gt;    &amp;lt;input type="submit" &lt;span style="color:green"&gt;name="_eventId_red"&lt;/span&gt; value="Red" /&amp;gt;&lt;br /&gt;  &amp;lt;/form:form&amp;gt;&lt;br /&gt;&lt;br /&gt; ...&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;i&gt;flowExecutionUrl&lt;/i&gt; contains the context-relative URL to the current flow execution's view state.  Alright, so what advantages does web flow provide?  Here are a few: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;Do your business users create use cases or flow charts?  If they do, those documents should map uniformly to web flows.  In fact, the business users that build the flow charts should be able to interpret your web flow definitions also.  Self documenting code that you can also share with the business is valuable.&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;Spring Web Flow provides an additional scope called flowScope.  Most applications suffer from session bloat because many developers put data into session out of convenience and do not always think about its consequence. Web Flow alleviates this problem with their flow scope. For example, flow scope is created when your flow starts. And when your flow ends, all data held within flow scope is cleaned up automatically.  Now you are running lean!  In the example below we put a list of colors in flowScope:&lt;/span&gt;&lt;pre style="font-family: Verdana, Arial, helvetica, sans-serif; border: 1px solid #CCCCCC; padding: 5px; overflow: auto; background-color: #f3f5e9; font-size: 12px; line-height: 14px;&lt;br /&gt;width: 100%;"&gt;&lt;code&gt;&amp;lt;flow start-state="start"&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;view-state id="start" view="chooseColor.jsp"&amp;gt;&lt;br /&gt;      &lt;span style="color:green"&gt;&amp;lt;on-render&amp;gt;&lt;br /&gt;        &amp;lt;evaluate &lt;br&gt;            expression="colorService.findAllColors()"&amp;nbsp;&lt;br&gt;            result="flowScope.colors" /&amp;gt;&lt;br /&gt;      &amp;lt;/on-render&amp;gt;&lt;/span&gt;&lt;br /&gt;      &amp;lt;transition on="red" to="showRed" /&amp;gt;&lt;br /&gt;    &amp;lt;/view-state&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;end-state id="showRed" view="red.jsp"/&amp;gt;&lt;br /&gt;&amp;lt;/flow&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;Spring Web Flow also has a built-in expression language.  The expression language is a feature that allows you to call your Spring beans conveniently from within your flows.  In the example above, we fetched our colors from the &lt;i&gt;ColorService&lt;/i&gt;.&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;There is less code to maintain compared to the other MVC frameworks.  You do not need controller objects anymore.  However, you still need to create model objects for binding form data to objects.  The form binding in web flow is automatic for simple types.&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;Your flows and transitions can be secured with Spring Security.  The example below shows how you may secure your web flow or a transition:&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: Verdana, Arial, helvetica, sans-serif; border: 1px solid #CCCCCC; padding: 5px; overflow: auto; background-color: #f3f5e9; font-size: 12px; line-height: 14px;&lt;br /&gt;width: 100%;"&gt;&lt;code&gt;&amp;lt;flow start-state="start"&amp;gt;&lt;br /&gt;    &lt;span style="color:green"&gt;&amp;lt;!-- secure the entire flow --&amp;gt;&lt;/span&gt;&lt;br /&gt;    &amp;lt;secured attributes="ROLE_USER" /&amp;gt; &lt;br /&gt; &lt;br /&gt;    &amp;lt;view-state id="start" view="chooseColor.jsp"&amp;gt;&lt;br /&gt;        &amp;lt;transition on="red" to="showRed"&amp;gt;&lt;br /&gt;           &lt;span style="color:green"&gt;&amp;lt;!-- secure this transition --&amp;gt;&lt;/span&gt;&lt;br /&gt;           &amp;lt;secured attributes="ROLE_ADMIN"/&amp;gt;  &lt;br /&gt;        &amp;lt;/transition&amp;gt;&lt;br /&gt;    &amp;lt;/view-state&amp;gt;&lt;br /&gt;     &lt;br /&gt;    &amp;lt;end-state id="showRed" view="red.jsp"/&amp;gt;&lt;br /&gt;  &lt;br /&gt;&amp;lt;/flow&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;You can achieve reuse with subflows and global transitions.&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: Verdana, Arial, helvetica, sans-serif; border: 1px solid #CCCCCC; padding: 5px; overflow: auto; background-color: #f3f5e9; font-size: 12px; line-height: 14px;&lt;br /&gt;width: 100%;"&gt;&lt;code&gt;&amp;lt;flow start-state="start"&amp;gt;&lt;br /&gt; &lt;br /&gt;    &amp;lt;view-state id="start" view="chooseColor.jsp"&amp;gt;&lt;br /&gt;        &amp;lt;transition on="red" to="showRedSubflow" /&amp;gt;&lt;br /&gt;        &amp;lt;transition on="green" to="showGreenSubflow" /&amp;gt;&lt;br /&gt;    &amp;lt;/view-state&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span style="color:green"&gt;&amp;lt;!-- subflow states --&amp;gt;&lt;/span&gt;&lt;br /&gt;    &amp;lt;subflow-state id="showRedSubflow" &lt;br&gt;        subflow="redSubflow.jsp" /&amp;gt;&lt;br /&gt;    &amp;lt;subflow-state id="showGreenSubflow" &lt;br&gt;        subflow="greenSubflow.jsp" /&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;end-state id="thankYou" view="thanks.jsp" /&amp;gt;&lt;br /&gt; &lt;br /&gt;    &lt;span style="color:green"&gt;&amp;lt;!-- If every page had a cancel button we may declare that transition once. --&amp;gt;&lt;/span&gt;&lt;br /&gt;    &amp;lt;global-transitions&amp;gt;&lt;br /&gt;      &amp;lt;transition on="cancel" to="cancel.jsp" /&amp;gt;&lt;br /&gt;    &amp;lt;/global-transitions&amp;gt;&lt;br /&gt; &lt;br /&gt;&amp;lt;/flow&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;Web flows are browser button friendly.  To achieve this, every view state rendered gets stored as a snapshot.  When you press the back button, the previous snapshot is retrieved from the snapshot repository. For performance, you may limit the number of snapshots that exist within the snapshot repository.&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;Web flows eliminate the double-submit problem.  To accomplish this, Spring will apply the &lt;a href="http://en.wikipedia.org/wiki/Post/Redirect/Get"&gt;POST-REDIRECT-GET&lt;/a&gt; pattern to all POST requests.  You may also disable this feature if it's not needed or if you want better performance.&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;As always, Spring has strong JUnit test support to help test your flows.&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;In conclusion, Spring Web Flow is a very unique MVC framework.  It is an ideal solution for simplifying complex work flows.  I particularly like the simplicity of the domain specific templating language (DSL), the flowScope, and the expression language capabilities.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-696192315842480408?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/696192315842480408/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/02/spring-webflow-elegant-dsl-for-your-mvc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/696192315842480408'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/696192315842480408'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/02/spring-webflow-elegant-dsl-for-your-mvc.html' title='Spring Webflow: An elegant DSL for your MVC'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-6566085250091844071</id><published>2009-02-19T18:14:00.011-06:00</published><updated>2010-01-31T10:14:10.388-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='accessibility'/><title type='text'>Designing for Accessibility</title><content type='html'>How accessible is your website? If you are interested in finding out, you may enter your URL at the &lt;a href="http://wave.webaim.org/"&gt;WAVE website&lt;/a&gt; for a quick evaluation. You may also download the &lt;a href="http://wave.webaim.org/toolbar"&gt;WAVE Firefox plug-in&lt;/a&gt; for even greater control.&lt;br /&gt;&lt;br /&gt;Well, did your site have any errors? Technically, you do not have anything to worry about unless your site is for a government agency. In any case, Web standards are a good thing to design for and this WAVE plug-in can be a great tool to help find any gaps you may have. In addition, this tool can also serve as another check list item for your next client-side code review.&lt;br /&gt;&lt;br /&gt;If you are interested in designing for accessibility, the effort is &lt;i&gt;minimal&lt;/i&gt;. For example, you can achieve nearly zero accessibility errors by simply focusing on these three categories:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create &lt;a href="http://webaim.org/techniques/forms/controls.php"&gt;accessible forms&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Create &lt;a href="http://webaim.org/techniques/images/alt_text.php"&gt;accessible images&lt;/a&gt; with &lt;a href="http://webaim.org/techniques/alttext/"&gt;appropriate alt text&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Use appropriate &lt;a href="http://webaim.org/techniques/semanticstructure/"&gt;heading&lt;/a&gt; and &lt;a href="http://webaim.org/techniques/tables/data.php"&gt;table header&lt;/a&gt; tags&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;You may be wondering about dynamic content. If you have dynamically updated content, you will also want to learn about &lt;a href="http://webaim.org/techniques/aria/"&gt;ARIA&lt;/a&gt; (Accessibility of Rich Internet Applications). For example, if you have data that gets dynamically updated within a &amp;lt;div&amp;gt; tag you can include aria attributes to notify assistive technologies of dynamic content updates. Here are several &lt;a href="http://wiki.codetalks.org/wiki/index.php/How_to_use_ARIA_Live_Regions_for_dynamic_content"&gt;examples&lt;/a&gt; that demonstrate how to make your dynamic content accessible. There is nothing to install to take advantage of ARIA. ARIA is supported in Firefox 3+ and IE 8+.&lt;br /&gt;&lt;br /&gt;In conclusion, the effort involved to implement these accessibility standards is relatively minor. In return, you are designing towards standards, your site is consumable by a larger user base, and you have just given your sales team another competitive advantage. The WAVE plug-in also gives you and your QA team an &lt;i&gt;automated&lt;/i&gt; tool to evaluate pages for accessibility compliance.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-6566085250091844071?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/6566085250091844071/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/02/designing-for-accessibility.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/6566085250091844071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/6566085250091844071'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/02/designing-for-accessibility.html' title='Designing for Accessibility'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-3053650361618749785</id><published>2009-02-12T18:13:00.010-06:00</published><updated>2009-03-12T22:16:58.448-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><title type='text'>A Spring Pattern for Error Logging</title><content type='html'>&lt;span style="font-family:arial;"&gt;Looking for an effective error logging solution? I recently found this pattern from the &lt;/span&gt;&lt;a href="http://bradbroulik.blogspot.com/2009/02/pro-spring-25-good-bad-and-ugly.html"&gt;&lt;span style="font-family:arial;"&gt;Pro Spring 2.5&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:arial;"&gt; team and it has several very elegant features which include: &lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;It is an AOP based solution so it will prohibit you from infecting your business logic with error logging details. &lt;i&gt;This concept isn’t new. The next two features I thought were more interesting&lt;/i&gt;.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;The log details are written to a database. In fact, the exception will only get written once. If an identical exception occurs the count of that occurrence will be incremented. &lt;i&gt;This reduces the redundancy that we see in file based solutions&lt;/i&gt;.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;For reporting purposes, the following exception details will be captured: &lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;number of occurrences &lt;i&gt;(nice feature)&lt;/i&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;exception name&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;class and method name&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;method arguments &lt;i&gt;(nice feature)&lt;/i&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;stack trace&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;timestamp of last occurrence&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;An example report may look like:&lt;/span&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5301695725304109074" style="WIDTH: 400px; HEIGHT: 44px" alt="" src="http://3.bp.blogspot.com/_mO_Jjc1RwAQ/SZNoLC31WBI/AAAAAAAAABQ/0JV6UWoKNcM/s400/error_report.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;There are two components necessary to complete this task. An aspect for identifying the level at which you want to capture exception logging. And secondly, a data access object to manage the persistence. Here's an example of the Spring Aspect that will intercept all Service method calls:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre style="font-family: Verdana, Arial, helvetica, sans-serif; border: 1px solid #CCCCCC; padding: 5px; overflow: auto; background-color: #f3f5e9; font-size: 12px; line-height: 14px;&lt;br /&gt;width: 100%;"&gt;&lt;code&gt;@Aspect&lt;br /&gt;@Component&lt;br /&gt;public class ErrorLoggingAroundAspect {&lt;br /&gt; &lt;br /&gt;    @Autowired&lt;br /&gt;    private ErrorLogDao errorLogDao;&lt;br /&gt; &lt;br /&gt;    @Around("execution(* com.mycompany.myproject.service.*Service*.*(..))")&lt;br /&gt;    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {&lt;br /&gt;        pjp.getSignature().getName();&lt;br /&gt;        try {&lt;br /&gt;            return pjp.proceed();&lt;br /&gt;        } catch (Throwable t) {&lt;br /&gt;            insertThrowable(t, pjp);&lt;br /&gt;            throw t;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;    private void insertThrowable(Throwable t, ProceedingJoinPoint pjp) throws IOException {&lt;br /&gt;        StringWriter stackTrace = new StringWriter();&lt;br /&gt;        t.printStackTrace(new PrintWriter(stackTrace));&lt;br /&gt;        stackTrace.close();&lt;br /&gt;        StringBuilder methodArgs = new StringBuilder();&lt;br /&gt;        for (Object argument : pjp.getArgs()) {&lt;br /&gt;            if (methodArgs.length() &gt; 0) methodArgs.append(",");&lt;br /&gt;            methodArgs.append(argument);&lt;br /&gt;        }&lt;br /&gt;        methodArgs.insert(0, "(");&lt;br /&gt;        methodArgs.insert(0, pjp.getSignature().getName());&lt;br /&gt;        ErrorLog errorLog = new ErrorLog(&lt;br /&gt;          t.getClass().toString(), stackTrace.toString(), methodArgs.toString());&lt;br /&gt;        this.errorLogDao.insert(errorLog);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt; &lt;br /&gt;public class ErrorLog {&lt;br /&gt;    private String exceptionName;&lt;br /&gt;    private String stackTrace;&lt;br /&gt;    private String method;&lt;br /&gt;    private int count = 1;&lt;br /&gt; &lt;br /&gt;    public ErrorLog(String exceptionName, String stackTrace, String method) {&lt;br /&gt;     this.exceptionName = exceptionName;&lt;br /&gt;        this.stackTrace = stackTrace;&lt;br /&gt;        this.method = method;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Here's the example DAO that will persist the exception to memory. A real solution would persist to a database.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;span class="code-highlight1"&gt;/** Persists to memory.*/&lt;/span&gt;&lt;br /&gt;@Repository&lt;br /&gt;public class ErrorLogDaoImpl implements ErrorLogDao {&lt;br /&gt; &lt;br /&gt;    private List&amp;lt;ErrorLog&amp;gt; errors = Collections.synchronizedList(new LinkedList&amp;lt;ErrorLog&amp;gt;());&lt;br /&gt; &lt;br /&gt;    public void insert(ErrorLog errorLog) {&lt;br /&gt;        for (ErrorLog log : this.errors) {&lt;br /&gt;            if (log.getMethod().equals(errorLog.getMethod()) &amp;&amp;&lt;br /&gt;                    log.getStackTrace().equals(errorLog.getStackTrace())) {&lt;br /&gt;                log.setCount(log.getCount() + 1);&lt;br /&gt;                return;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        this.errors.add(errorLog);&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    public List&amp;lt;ErrorLog&amp;gt; getAll() {&lt;br /&gt;        return this.errors;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;In addition to the code above, you will also need to include &lt;i&gt;&amp;lt;aop:aspectj-autoproxy/&amp;gt;&lt;/i&gt; within your Spring configuration file. This tag scans for @Aspect's and turns them into proxies. &lt;br /&gt;&lt;br /&gt;Again, I like this solution because it keeps the business-tier clean of logging details, there are no redundant error log messages like we see with file-based solutions, and the persisted data allows for much simpler error reporting.  In addition to error logging, I also see this pattern being a good solution for business auditing too.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-3053650361618749785?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/3053650361618749785/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/02/spring-pattern-for-error-logging.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3053650361618749785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/3053650361618749785'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/02/spring-pattern-for-error-logging.html' title='A Spring Pattern for Error Logging'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_mO_Jjc1RwAQ/SZNoLC31WBI/AAAAAAAAABQ/0JV6UWoKNcM/s72-c/error_report.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-9174066286049248867</id><published>2009-02-07T11:20:00.023-06:00</published><updated>2009-02-08T10:58:54.038-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>Pro Spring 2.5: the Good, the Bad, and the Ugly</title><content type='html'>&lt;a href="http://apress.com/book/view/1590599217"&gt;&lt;span style="font-family:arial;"&gt;Pro Spring 2.5&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:arial;"&gt; covers the new 2.5 additions to the Spring framework. The &lt;/span&gt;&lt;a href="http://apress.com/book/downloadfile/4095"&gt;&lt;span style="font-family:arial;"&gt;table of contents&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:arial;"&gt; is viewable from the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Apress&lt;/span&gt; web site.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:arial;"&gt;The Good:&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;In addition to the new core framework features (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;JDBC&lt;/span&gt;, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;AOP&lt;/span&gt;, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;remoting&lt;/span&gt;, transaction management) they also included chapters about Spring &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;MVC&lt;/span&gt;, Spring Web Flow, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;JMX&lt;/span&gt;, testing, and performance tuning. &lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;The authors do a good job of including introductory content for new Spring users. In fact, the first eight chapters (Part I) were targeted towards users getting started with Spring. &lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;The author's explain many of the new features in great detail and had code examples for nearly everything. However, there are some gaps in their code examples.&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;If you are a fan of &lt;/span&gt;&lt;a href="http://www.javapuzzlers.com/"&gt;&lt;span style="font-family:arial;"&gt;Josh Bloch's puzzler's&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:arial;"&gt; then you will &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_6"&gt;definitely&lt;/span&gt; enjoy some of the code examples. The disappointing point is that these were not intentional mistakes! If you do not like puzzlers, then move this one to the bad and ugly category. &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:arial;"&gt;&lt;strong&gt;The Bad and Ugly:&lt;/strong&gt; &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:arial;"&gt;The source code examples in this book contained many typos and copy-paste errors. More than I had ever seen an any book previously. Unfortunately, this may cause confusion for new Spring users. &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;strong&gt;My recommendation (3.9 stars out of 5):&lt;/strong&gt;&lt;br /&gt;I originally &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;pre&lt;/span&gt;ordered this book based on the reputation of the first &lt;/span&gt;&lt;a href="http://www.amazon.com/Pro-Spring-Rob-Harrop/dp/1590594614"&gt;&lt;span style="font-family:arial;"&gt;Pro Spring&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:arial;"&gt; book. That book was very good and it had &lt;em&gt;great&lt;/em&gt; reviews to back it up. Despite the typo's, I &lt;em&gt;have&lt;/em&gt; found value in this book. I have given brown bags on the new features of Spring, Spring MVC, and Spring Web Flow and I gathered most of my content from this book. This book has been a good compliment to the &lt;/span&gt;&lt;a href="http://static.springframework.org/spring/docs/2.5.x/reference/"&gt;&lt;span style="font-family:arial;"&gt;Spring reference documentation&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:arial;"&gt;. However, If you can't tolerate an &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_9"&gt;occasional&lt;/span&gt; typo then you may want to avoid this book completely. &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-9174066286049248867?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/9174066286049248867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/02/pro-spring-25-good-bad-and-ugly.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/9174066286049248867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/9174066286049248867'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/02/pro-spring-25-good-bad-and-ugly.html' title='Pro Spring 2.5: the Good, the Bad, and the Ugly'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-815218331733895214</id><published>2009-02-04T17:35:00.003-06:00</published><updated>2009-02-04T18:40:59.638-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books'/><title type='text'>97 Things Every Software Architect Should Know – The Book</title><content type='html'>&lt;a href="http://www.monson-haefel.com/"&gt;Richard Monson-Haefel's&lt;/a&gt; list of &lt;a href="http://97-things.near-time.net/wiki"&gt;97 Things Every Software Architect Should Know&lt;/a&gt; is expected to be released soon by O'Reilly. I personally want to thank Richard for assembling this great list! We have always seen the architectural and programming design pattern books on the shelves but this one will be an awesome compliment.&lt;br /&gt;&lt;br /&gt;I think these types of books where content is submitted by many contributors will become much more popular going forward. &lt;a href="http://career20.blogspot.com/2009/01/whats-your-strategy.html"&gt;Career 2.0&lt;/a&gt;, by &lt;a href="http://www.nfjsone.com/conference/speaker/jared_richardson.html"&gt;Jared Richardson&lt;/a&gt;, is another new book where the content was gathered in a similar fashion. In fact, you may submit your experiences for this book now on their Career 2.0 &lt;a href="http://career20.blogspot.com/"&gt;blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Is this a trend? Not sure, but it is interesting.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://career20.blogspot.com/2009/01/whats-your-strategy.html"&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-815218331733895214?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/815218331733895214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/02/97-things-every-software-architect.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/815218331733895214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/815218331733895214'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/02/97-things-every-software-architect.html' title='97 Things Every Software Architect Should Know – The Book'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7224548894465589501.post-1769331247942717601</id><published>2009-01-27T19:35:00.001-06:00</published><updated>2009-02-07T14:01:40.611-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conferences'/><title type='text'>Developing Expertise</title><content type='html'>Looking for an exciting talk on developing expertise? I &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_0"&gt;definitely&lt;/span&gt; recommend &lt;a href="http://pragdave.pragprog.com/"&gt;Dave Thomas&lt;/a&gt;' talk on "&lt;a href="http://www.infoq.com/presentations/Developing-Expertise-Dave-Thomas"&gt;Herding racehorses and racing sheep&lt;/a&gt;." I was fortunate enough to attend this talk at &lt;a href="http://www.nofluffjuststuff.com/home.jsp"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;NFJS&lt;/span&gt;&lt;/a&gt; back in 2003 and it is still a classic. The talk is also very humorous:) The wizard vs wizard argument and the wizard vs novice points were hilarious. Thanks Dave, this advice has been very helpful for me over the years!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7224548894465589501-1769331247942717601?l=bradbroulik.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bradbroulik.blogspot.com/feeds/1769331247942717601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bradbroulik.blogspot.com/2009/01/developing-expertise_27.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1769331247942717601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7224548894465589501/posts/default/1769331247942717601'/><link rel='alternate' type='text/html' href='http://bradbroulik.blogspot.com/2009/01/developing-expertise_27.html' title='Developing Expertise'/><author><name>Brad Broulik</name><uri>http://www.blogger.com/profile/14248585105589786365</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/-Ro9ER2gWiyI/TuOrOP5oKJI/AAAAAAAAAKY/CJbg7TQKdfg/s220/BradBroulikBioPhoto-sent.jpg'/></author><thr:total>0</thr:total></entry></feed>
