<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>Ben Northrop - Decisions and Software Development</title>
    <link>http://www.bennorthrop.com/</link>
    <description>Thoughts on economics, philosophy, and building software.</description>
    <language>en-us</language>
	<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
	<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://www.bennorthrop.com/rss.php" />
	<feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="BenNorthrop" />
	<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" />
	<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
  
    <pubDate>Mon, 29 Dec 2025 00:00:00 -0500</pubDate>
		<item>
			<title>A 2025 Year in Review for Highline</title>
			<link>https://www.bennorthrop.com/Essays/2025/year-in-review-highline.php</link>
			<description>
				<![CDATA[				<p>
What a year.  
</p>

<p>
If I'm honest, from the day-to-day perspective, 2025 felt like a non-stop stream of uncertainty and struggle and just...ugh.  
</p>

<p>
It came from all directions.  
</p>

<p>
The general economy was...let's go with "choppy" - with tariffs and shutdowns and budgets cuts, oh my.  AI rapidly morphed from a new and exciting efficiency booster to a possible existential disruption to our entire field.  And in our own little world, Highline battled with a bit of an identity crisis - who are we and, more importantly, who <i>should</i> we be?  
</p>

<p>
It was all a bit discombobulating.
</p>

<img src="https://www.bennorthrop.com/Essays/2025/pat-medium.jpeg" style="display: block; margin-left: auto; margin-right: auto; width: 250px; border: solid 1px black" class="mobile-wide-image" align="center"/>


<p>
That's not to say everything in years prior has been rainbows and unicorns.  We've had trials and obstacles.  But 2025 was a struggle.  No doubt about it.  
</p>

<p>
Isn't that what makes the journey meaningful though?
</p>

<p>
With the benefit of a few days of rest and reflection, as I look back at the year, I'm probably more proud of this year than any other in terms what we've learned and built, how we've adapted and changed course, and how we've stayed true to what <a href="https://www.bennorthrop.com/Essays/2024/highline.php">we believe in and we're all about</a>.   
</p>

<p>
Here are my three favorite highlights from this year...
</p>

<p>
<b>Highlight #1:</b> In January, we launched Highline Coding Academy.  After the pandemic forced so much of our lives into the virtual realm, our hope was to bring people of all ages out into the physical world to connect and build and learn and have a little fun.  In this first year, we offered 21 different events and classes, facilitated by about a dozen different presenters and teachers, and welcomed 500 unique registratrants.  Pretty great start.  
</p>


<img src="https://www.bennorthrop.com/Essays/2025/weston-medium.jpeg" style="display: block; margin-left: auto; margin-right: auto; width: 250px; border: solid 1px black" class="mobile-wide-image" align="center"/>


<p>
And it was never about the money - which is a good thing, because (shocker!) we learned quickly that the economics of in-person education are not what you would call "strong".  Instead, it was about planting the seeds of inspiration and creativity, and allowing for the serendipity of real world interactions.  In terms of both of those, our little Coding Academy was a big success.  Hearing from a few kids about coding projects they started on their own was a delight.  And our professional events allowed us to make some connections and re-connections with friends and other like-minded builders.  
</p>




<p>
Lastly, it also gave us a chance to eat some amazing <a href="https://www.rockawaypizzeria.com/">Rockaway pizza</a> on the regular. 
</p>

<p>
<b>Highlight #2:</b> Bootstrapping a company isn't easy.  7 years ago, when it was just me, I was stressed to the MAX about what a late or no-payment would do to my family's personal finances, or what would happen if that next contract didn't come through.  And this stress obviously didn't abate as we on-boarded employees and contractors over the ensuing years.  Understanding and managing cash flow is a scary thing - especially when your degrees are in philosophy and information systems, not business.  
</p>

<p>
In 2025 though, after 6 years of business frugality, Highline finally got to a place of solid financial stability, and all without any investment or debt.  With the help of some great advisors (and a few business self-help books), I now lose ZERO sleep about late or no-payments - though, to be clear, I still want us to be paid!
</p>
 
<p>
This stability allowed us to do some new things - for example, this year we put into place a concept called "bench insurance", where full-time employees pay a small percentage of their billable rate into what we call a "bench pool", which we manage in a prescribed and transparent way.  We've since accrued enough in our pool to allow for a guaranteed month worth of bench compensation for every employee, which gives a little peace of mind when contracts wind down. 
</p>  

<p>
<b>Highlight #3:</b>  On the delivery side, while I can't share too many of the nitty gritty details, in 2025 we delivered some truly great projects for our clients.  In the spring, we assembled a strike force team to build a mobile app and admin console for a client in the health care space.  The timeline was extremely tight, the scope a bit murky at the start, and the deliverable crucial for their business.  Highline delivered on time, on budget, and even took on a bit of extra scope.  One of the best team efforts I've been apart of.
</p>

<p>
For other clients, we contributed to dozens of releases of different applications, services, and pipelines that helped their businesses in innumerable ways - like eliminating manual data entry for office staff, giving and tracking refunds for customers, helping to streamline the delivery of food to patients in long-term care facilities, and a ton of other great things.  
</p>

<p>
TLDR; we built some really cool shit.  
</p>

<p>
Well, now I'm on a roll...but I'll stop at these 3...though I have to say, I'm also super grateful for the awesome new people we've welcomed on board in 2025 as well as the equally awesome people we helped transition to full-time roles at clients.  
</p>

<p>
Maybe it's just a function of this cozy time between holidays when work ebbs and stress fades that's adding a degree of sentimentality, but honestly as I look back, 2025 was, after all, pretty great.  Despite all challenges, we persevered.  
</p>

<p>
It wasn't about revenue numbers or profit margins - it's that we continued to build quality software and also stay true to what we're about: rewarding those doing the work and enjoying the collaborative process with people around us.

<p>
No matter where AI takes things, we'll be siding with the humans.
</p>

<img src="https://www.bennorthrop.com/Essays/2025/handerson-ai-medium.jpeg" style="display: block; margin-left: auto; margin-right: auto; width: 250px; border: solid 1px black" class="mobile-wide-image" align="center"/>

<p>
In the end, I'm super grateful for everyone who took a chance on our little company, for all the great work they do, and the professionalism and commitment with which they do it.
</p>


<p>
Happy New Year!
</p>				]]>			</description>
			<pubDate>Mon, 29 Dec 2025 00:00:00 -0500</pubDate>
			<guid>https://www.bennorthrop.com/Essays/2025/year-in-review-highline.php</guid>
		</item>
		<item>
			<title>Meanwhile at Highline Solutions...</title>
			<link>https://www.bennorthrop.com/Essays/2024/highline.php</link>
			<description>
				<![CDATA[				<section id="setup-blurb">
As <a href="https://highlinesolutions.io">Highline Solutions</a> turns six, I just wanted to step back and write a bit about what we've built, our mission, and the values we've formed on our journey.    
</section>

<img src="https://www.bennorthrop.com/Essays/2024/highline-group-1.png" style="display: block; margin-left: auto; margin-right: auto;" class="mobile-wide-image" align="center"/>

<p class="indentable">
<i>“The point of the organization is to enhance the lives of the people who are part of it.” 
<br/>--<a href="https://www.amazon.com/Anarchists-Approach-Building-Business-Zingermans/dp/0964895684">Ari Weinzweig</a></i>
</p>
<p>
Highline is a bit different from traditional consulting companies in terms of, well, everything - how we’re structured, how we compensate, and what we believe.  That’s not to say that we’re “right” and everyone else is “wrong” - it’s all about trade-offs.  At Highline, we value choice, autonomy, and freedom, but that can come at the expense of some other “good” things - like predictability, consistency, and structure.  Plotting Highline versus other “gigs”, it might look something like this:
</p>

<img src="https://www.bennorthrop.com/Essays/2024/highline-vs-others.png" style="display: block; margin-left: auto; margin-right: auto;" class="mobile-wide-image" align="center">

<p>As you read on, it’ll become more clear why we put Highline where it is on the line above. And again, neither left, right, or center is “best” - it’s all about a person's preferences, circumstances, and goals. 
</p>

<h2>The Premise</h2>
<p>
To start, it’ll be helpful to begin with the basic premise of our company, which is this:
</p>

<p class="indentableSubtle">Reward the person doing the work</p>

<p>
For good or bad, most consulting companies run off the “billable hour” - revenue is generated by clients who pay for hours worked by consultants.  And since it is the company who handles the terms, contracts, and payments, it’s the company that gets to decide how to divvy things up.  Typically, the split looks something like this:
</p>

<img src="https://www.bennorthrop.com/Essays/2024/highline-premise-1.png" style="display: block; margin-left: auto; margin-right: auto;" class="mobile-wide-image" align="center">

<p>
For every hour billed, consultants take about 50% of their hourly rates in terms of salary, bonuses, and benefits, and the money remaining is used by the company for a variety of things, like supporting back office functions (sales, marketing, recruiting, accounting, etc.), providing tools and office space, and paying out bonuses to investors and executives.  Note that this split can vary depending on a consultant’s seniority, the domain or size of the company, and other factors.  And again, there is nothing inherently “bad” about this model.  Our goal with Highline though is to show that while the traditional model does have a proven track record, it doesn’t necessarily <i>have</i> to be this way.  
</p>

<p>
As an alternative, Highline’s endeavors to have the picture look more like this:
</p>

<img src="https://www.bennorthrop.com/Essays/2024/highline-premise-2.png" style="display: block; margin-left: auto; margin-right: auto;" class="mobile-wide-image" align="center">

<p>
First, we aim for our consultants to make a much larger share of their bill rate (closer to 80%, plus or minus), and also for them to make a larger absolute value than they would make at a more traditional consulting company.  This is based on our belief that if you’re the one out there on the front lines working with clients, then it’s you who should take home the majority of what the client is paying for <i>your</i> hour.  Secondly, as a competitive advantage, we try to keep our hourly rates less than other companies in our space (by about 20%, plus or minus).  Putting these two things together - paying a bit more (and therefore attracting and retaining great people) and charging a bit less - we hope it’ll make for a compelling case for clients to consider and continue to work with us.  And this has been the case so far.
</p>

<p>
Of course, you probably realized that there’s an obvious consequence to this - there's less money left over for the company itself to run the business.  This is real.  And so we cut out the frills, eliminate the bureaucracy, and run as lean as we can.  In practice, this means that many traditional business functions are completely absent at Highline (like sales or marketing), and other back-office functions are handled by consultants themselves (as "extracurricular roles", which are compensated).
</p>

<p>
This model -  pay more, charge less, and run lean - as basic as it is (i.e. “duh”), so far has yielded some great results.  Over the past few years, we’ve assembled an amazing group of individuals (over 20 at the moment), built a fun and healthy culture, and delivered quality software to our clients which in turn helps their businesses thrive.  So we’re off to a good start in proving that our Premise is viable.  But there’s more to what we’re doing than just this.
</p>

<h2>Values</h2>
<p><i>
“The place to improve the world is first in one's own heart and head and hands, and then work outward from there.” 
<br/>-– Robert Pirsig, <a href="https://www.amazon.com/Zen-Art-Motorcycle-Maintenance-Inquiry/dp/0061673730/ref=sr_1_1?crid=1MVCW8UCEPT4N&dib=eyJ2IjoiMSJ9.gZaX8sujeOL9Nmw8n5Bqs8P88BmtvVogze_lx6dg5dDjcUmum6b0ybLobyIQIusRi72YxkwGjiWVlVqTFwwmpI8RomzydpRH5CLpMHPxN2-YvQ46OxbBNoyf6nhhzeaH6xDsWIomY01whWa0Zuu1tQj9aAxbx9ebHDRweZZzEP7QCpODhvh2wAF2XjE7A5HaS_FEHdvjgIlpR1pZXNm2rD8gAjGEZVeR9CvSmTKBdFo.xzy3s96515zLJGycUyfYtlk7i4zSV-T7tOK8BfNL4jg&dib_tag=se&keywords=zen+and+the+art+of+motorcycle+maintenance&qid=1727364307&s=books&sprefix=zen+%2Cstripbooks%2C89&sr=1-1">Zen and the Art of Motorcycle Maintenance</a>
</i></p>

<p>
Building off our core premise, we’ve begun to put shape to a few core values.  These are things that not only make us successful in what we do, but just as importantly help us achieve balance and meaning in our lives.
<p>

<h3>1. Focus on the Work</h3>
<p>
First and foremost, we are people who believe in the work.  We are builders, and creators, and tamers of complexity.  Our focus is not on winning deals, growing accounts, or increasing margins.  Our goal is to build quality software.  That’s it.  We believe the rest will sort itself out.
</p>

<p>
In practice, this value manifests itself in a couple of ways.  First, as mentioned above, our goal is to reward the person doing the work, and so we aim to give consultants a larger share of their bill rate than they would likely get at other companies. Going further, at a cultural level, we consider the “heroes” of our organization to be the consultants grinding it out in the trenches for our clients, and <i>not</i> the sales people signing contracts, the strategists crafting new elevator pitches, or the execs twiddling with spreadsheets.  Our focus is building great software, whether that means writing robust code, designing delightful experiences, or managing teams to successful outcomes.  This is the soul of what we do.
</p>

<p>
Second, <i>Focusing on the Work</i> means being pragmatic and solution-oriented.  We know the process of building software is inherently complex, where constraints are few, expectations are high, and solution spaces are limitless and malleable.  Given this, we <i>expect</i> frustration and even thrive in it (on our best days, at least).  Rather than getting tangled in the problems, tensions, and the ever-present risks, we calmly and resolutely focus on the work, and find our way to a workable solution.  
</p>


<h3>2. Keep it Simple, Streamlined, and Flat</h3>
<p>
As mentioned in the Premise, giving consultants the lion’s share of their billable hour means that there’s less leftover to run the business.  For Highline to be successful then we must keep processes, organizational structures, and policies as simple as possible.  We literally cannot afford bloat.  (Also, we hate it).  
</p>

<p>
In practical terms, this means that there are no back-office positions, and basically no hierarchy at Highline.  Everyone is a Consultant.  Some consultants have more experience than others, and can therefore command higher bill rates (and compensation) or more senior roles on a given project.  And some consultants may even take on “extracurricular roles” which give them responsibilities (and compensation) for helping with operations.  At the end of the day though, within Highline, we are all peers.  
</p>

<p>
It’s important to note that to function effectively without hierarchy, we must rely on both less structured lines and forms of communication and collaboration, and also on the assertiveness of individuals to navigate our network to get what they need.  This means that we drop 1-1 meetings on each others’ calendars, initiate impromptu working sessions at coffee shops (or breweries!), and send important and unimportant (memes!) information over Slack to keep eachother in the loop.  Rather than a command-and-control organization, we are more like a decentralized bee colony, each individual focused on their task, heeding common rules and norms, minding others, and getting work done.  
</p>

<h3>3. Listen and Be Humble</h3>
<p>
We are not the consultants who label themselves as “thought leaders”, who push the latest trendy processes or technologies, or who spend meetings talking about ourselves and our methods.  Quite the opposite.  We are listeners and learners.  We have confidence in our experience and abilities, yes, but that confidence is accompanied by a humility in knowing that the best solutions are a composite of ideas, suggestions, and compromises from all stakeholders.  In other words, there is wisdom in the crowd, and we stay open and attuned to it.
</p>

<p>
On projects, we start by <a href="https://www.bennorthrop.com/Essays/2018/unfolding-the-architecture-first-ask-questions.php">asking questions</a>.  Lots of them.  Our aim is to understand the context and contours of the problem space as much as possible before we break ground.  What we know is that it’s not just about building software right, but about building the <i>right software</i>, and to do that requires listening.  As we do inject our expertise and vision  into our projects, we do so without being wedded to our own solutions.  Software development is <a href="https://www.bennorthrop.com/Essays/2020/myth-of-software-architect-as-chess-master.php">about trade-offs</a>, and our goal is to present options with pros and cons, and help navigate and execute toward the best path.
</p>


<img src="https://www.bennorthrop.com/Essays/2024/highline-group-2.jpg" style="display: block; margin-left: auto; margin-right: auto;" class="mobile-wide-image" align="center">

<h3>4. Choose Quality, Lifestyle, and Balance</h3>
<p>
Finally, we are human beings.  We love what we do, but we also have lives outside of work - family, friends, hobbies, and commitments.  And so we strive to keep it all in balance for the sake of our happiness (and sanity).  As a natural and fortuitous consequence, the balance and calm we carve out for ourselves also benefits us in our work.  Rather than being frazzled and time-constrained, we have space to be thoughtful, creative, and productive for our clients.
</p>

<p>
Further, in support of balance, we try not to overextend.  This goes for us as individuals and as well as for Highline as a company.  As consultants, we take on only as much as we choose - whether that means 20, 30, or 40 hours a week - and step away for vacation and time off as much as we’d like.  (This comes with a trade-off for earning potential, but it is our choice.)  As an organization, we don’t take on projects for the sake of “growing the business”.  If we believe we have the skills and capacity to succeed on a project, we will.  If not, we’ll pass.  We don’t chase growth for its own sake or for the sake of profit, but we do consider and accept it if it makes our collective group more sustainable or gives us more choice.     
</p>

<h2>Conclusion</h2>
<p>
I am really proud of what we've built at Highline over the past 6 years.  It's not perfect, but we try to take a growth mindset on our journey - accepting that we're not going to get it all right from the start, but learning from our mistakes and incrementally making things better.
</p>

<p>
Happy to hear your thoughts, or if you'd like to talk about software we could build for you, please reach out!  We'd love to help if we can.
</p>				]]>			</description>
			<pubDate>Tue, 01 Oct 2024 00:00:00 -0400</pubDate>
			<guid>https://www.bennorthrop.com/Essays/2024/highline.php</guid>
		</item>
		<item>
			<title>The Ambiguous Zone</title>
			<link>https://www.bennorthrop.com/Essays/2023/the-ambiguous-zone.php</link>
			<description>
				<![CDATA[				<p>In my experience, it's easy for developers (me included) to hang out at either end of the following spectrum:</p>

<img src="https://www.bennorthrop.com/Essays/2023/ambiguous-zone.png" style="display: block; margin-left: auto; margin-right: auto;" class="mobile-wide-image" align="center">
<p>
On the left is when we <b>stay in our lane</b>.  We're given a requirement, we interpret the requirement, and then we make it so.  Easy peasy.  <i>But what's that?  The requirement didn't mention validation and it's a form submission screen?  Must be it's not needed!  We just do what we're told.</i>  And likely we're not this pedantic, but the point is that it's comfortable at this end.  We get work done, and we don't make waves.  If something isn't right, we were just following orders.
</p>

<p>
On the other end is when we <b>go rogue</b>.  We find some "requirement" that might be useful (but no one really asked for), or some new approach or technology that's interesting or "hot", and then spend the entire sprint in our coding cave joyfully building it out.  Will it actually help the project?  Err...maybe?  Regardless though, it'll be fun, because we love nothing more than smooth sailing - not being beholden to the ideas, thoughts, or reservations of others (well, that is, until they see our 4k-line pull request!).
</p>

<p>
Unfortunately, in neither of these states does valuable work get done. I mean...sure, <i>something</i> is produced, but it's rarely the right thing - i.e. the thing the users or the business actually needs.  Because this "right" thing is really hard to figure out.  It requires  understanding the business context, priorities, and time constraints.  It requires understanding the needs, preferences, and behaviors of the users.  And it requires understanding the existing implementation and the scope and impact of what is to be built.  All of this must be hashed through to get it "right", and this "hashing through" process is what happens in the Ambiguous Zone.  It's messy and frustrating, but it is the only way to produce something of real value.
</p>

<p>
The most effective developers I've worked with understand this, and are adept navigating this zone.  They are curious about the perspectives and needs of other stakeholders, and <a href="https://www.bennorthrop.com/Essays/2018/unfolding-the-architecture-first-ask-questions.php">ask good questions</a>.  They push back when things don't make sense, but do so tactfully.  And they understand the realities of building software in an industry context, where there are budgets, deadlines, and other less-than fun realities.  They don't expect everything is perfectly spelled out for them (whether by designer, business analyst, or architect), because they know, as the one closest to the implementation, they have a crucial perspective to voice.  But they also know they don't have all the answers.  In other words, they know that building the right software is a <b>back-and-forth, collaborative process</b>.
</p>

<p>
But not every developer or team works well in this Ambiguous Zone.  And there is a tell-tale sign when it's being avoided: the conspicuous lack of discussion.  When we're either doing only what we're told or only what we want, we have no need to talk with others.  It's all laid out for us, either in a requirements spec or in our heads.  If we do happen to meet, there is no disagreement, no requests for clarification, no passionate exchanges.  And while it's alluring to think this quietude is a sign of efficiency or productivity (meetings suck, amiright!), it's NOT.  Instead, it's a sign the team is avoiding the Ambiguous Zone, and the end product will be off target.
</p>

<p>
It's understandable though why we would avoid it - it's both risky and frustrating in there!  First, we know that there's a real chance we may never make it out.  We'll flounder in <a href="https://www.bennorthrop.com/Essays/2022/going-solo-good-and-bad-of-bull-shit.php">meeting after meeting</a> with no resolution, and never get to build anything.  (At least when we do what we're told or what we want, something gets produced.) It's also very hard to operate within the Ambiguous Zone, because it means navigating the imprecisions and imperfections of other human beings.  This was tricky in "normal times", but probably more so in a remote-first environment (without the benefit of hallway conversations or other in-person interactions that build trust and enable quick information flow).  Without these discussions, we don't understand the context, we don't voice our perspective, and we often don't find the right solutions.
</p>

<p>
My sense is that the Ambiguous Zone is an inconvenient truth about programming in industry.  We're often driven to the field because it's deterministic and precise, but when we get here, it's much more fuzzy than we expect.  In other words, there's a mismatch between the perception and the reality.  Just look how we interview.  We ask candidates to solve esoteric programming puzzles (i.e. do what you're told) or assess whether they built some interesting side project (i.e. do what you want), but rarely do we evaluate whether they can navigate ambiguity in a collaborative setting, which is just important to being an effective developer in the "real world".  As an industry, we should emphasize, encourage, and train for this more.  Happy to hear your thoughts!
</p>
				]]>			</description>
			<pubDate>Mon, 20 Mar 2023 00:00:00 -0400</pubDate>
			<guid>https://www.bennorthrop.com/Essays/2023/the-ambiguous-zone.php</guid>
		</item>
		<item>
			<title>The Fallacy of Splitting Time</title>
			<link>https://www.bennorthrop.com/Essays/2022/fallacy-of-splitting-time.php</link>
			<description>
				<![CDATA[				<p>
There's an illusion many people have around splitting time across projects.  I see it all the time, and I often fall for it myself.  Here's a simple example:
</p>

<p class="indentableSubtle">
There are two projects, both deemed important by the business, and both need a UI developer.  Unfortunately, only one UI developer is available.  The manager has an idea though: why not just let the UI developer split his time across both projects.  Sure, this will slow the pace a bit for each project, but at least they'll be moving in the right direction.  
</p>

<p>
So what's wrong with this?  While it's true that the UI developer should be able to contribute in some productive way to each project, what's faulty here is the hidden assumption.  The manager typically expects in this scenario that each project will effectively be getting one half of a developer worth of productivity.  In reality, <b>both projects will get less than one half</b> (and possibly much less).  Here's why...
<p>

<p>
The amount produced by a developer can be calculated like this:
</p>

<p class="indentable" style="font-family: courier new">
    Productive Time = Total Time - Overhead
</p>

<p>
Total Time is the number of hours you're on the clock - say, 40 - and Overhead can be split into two pieces.  The first is the Fixed Overhead - things we need to do as part of our job, like checkpoints with the boss, company meetings, etc. (see <a href="https://www.bennorthrop.com/Essays/2022/going-solo-good-and-bad-of-bull-shit.php">bullshit</a>).  This type of overhead just comes with the particular company we work for, and there's not much we can do about it.  Assuming a Fixed Overhead of 10%, that would leave 90%, or roughly 36 hours, left over.
</p>

<p>
The other type of overhead that needs to be subtracted out is specific to the project, and so we can call this...wait for it...Project Overhead.   This is the time we need to spend in order to just keep pace with the project as it's moving along, and includes things like reading emails/IMs, attending meetings (stand-ups, backlog groomings, etc.), and other basic communication and coordination necessary to understand the current state of things.  And this is where the fallacy comes into play.  We often forget that <b>each project has its own overhead</b> - work that needs to be done before we can start doing anything truly productive - and when you add all of these overhead activities up, it's not uncommon that this could sum to 15% or more of your time per project.  Given the example above, this would leave the UI developer with only 60% total productivity, or 30% for each project. 
</p>

<img src="https://www.bennorthrop.com/Essays/2022/fallacy-of-splitting-time.png" style="display: block; margin-left: auto; margin-right: auto;" class="mobile-wide-image" align="center">

<p>
And this is why each project team will get less than half of a full developer's worth of work.
</p>
<p>
Now it's important to note that Project Overhead is variable, and is <b>primarily a function of how many people are on each project team</b>.  The larger the team, the more knowledge that needs to flow back and forth, and so the more time that's necessary to absorb this knowledge.  On big teams, it could easily take 20% of your time to coordinate with your team before you can contribute something of value.  And again, if you're splitting your time across two big projects, this premium would be paid twice.  
</p>

<p>
The flip side, however, is that on solo projects, there is effectively no Project Overhead, and so the fallacy doesn't really apply.  You can happily float back and forth between the two, because there's basically no switching cost (aside from the nominal costs of booting up your local dev environment, loading the project details into your brain, etc.).  In my experience though, these types of solo missions are rare.
</p>

<p>
Finally, the problem is especially bad when a developer gets split across 3 or even more projects (which I have seen).  This is pure insanity.  After incurring the Project Overhead costs for each of the projects, the developer has almost no Productive Time, and basically can't get anything done. And it's not their fault.  
</p>

<img src="https://www.bennorthrop.com/Essays/2022/fallacy-of-splitting-time-3-projects.png" style="display: block; margin-left: auto; margin-right: auto;" class="mobile-wide-image" align="center">

<p>
So why do we fall for this fallacy?  I think there are two reasons.  First, I think it's fair to say that as a group, we developers like to get our hands dirty on lots of things.  It enables us to learn more, which is something we enjoy, but also something we know is <a href="https://www.bennorthrop.com/rewrite-or-refactor-book/chapter-3-why-we-rewrite-even-when-we-shouldnt.php">good for our career</a> (and earning potential).  And so we accept being split across multiple projects out of self interest and optimism.  <i>And full disclosure, I do this shit to myself all the time.</i>
</p>

<p>
The second reason is that the ones making this decision for us to split our time are typically the managers, and managers aren't always tapped into the same reality that we live in.  The reason, I think, is that a manager's work <i>is</i> Overhead (in the way that I've defined it).  They keep up to speed with what people are doing and how projects are tracking, and this is incredibly valuable to the organization, but the need for them to have <a href="http://www.paulgraham.com/makersschedule.html">dedicated time to produce something</a> is much lower than for other roles (which includes not just developers, but BAs, designers, etc.).  And so because <i>they</i> don't require a solid chunk of Productive Time for themselves, they might forget that <i>we</i> do.  <i>Note: I'm just spitballing here!</i>
</p>

<p>
In the end, I'm curious what people think.  Do you agree that this is a thing? How pervasive is the strategy of splitting time across projects?  Do we generally understand the effects on productivity?  And are there other things at play that reduce productivity when splitting across projects?
</p>
				]]>			</description>
			<pubDate>Wed, 15 Jun 2022 00:00:00 -0400</pubDate>
			<guid>https://www.bennorthrop.com/Essays/2022/fallacy-of-splitting-time.php</guid>
		</item>
		<item>
			<title>Going Solo and Dark Alleys</title>
			<link>https://www.bennorthrop.com/Essays/2022/going-solo-dark-alleys.php</link>
			<description>
				<![CDATA[				
<p>
After twenty or so years as a software developer, mostly in consulting, I felt like I could handle myself in even the most tenuous situations.</b>

<p>Sure, there were the miscommunications around scope or requirements.  Or differences of opinion on technical solutions or philosophy.  Or even just general stress around tight deadlines.  But in any of these scenarios, I always felt like "I got this".  I could navigate through just about anything, at least without ruffling too many feathers or dropping the ball too egregiously.  Things were comfortable, more or less.
</p>

<p>
Then I went out <a href="https://highlinesolutions.io">on my own</a>.  And immediately it felt different.  
</p>

<img class="content-image" src="http://www.bennorthrop.com/Essays/2022/chuck-norris.png" width="250" />

<p>
Of course I expected this to some extent, but I was surprised at the degree to which I felt exposed.  It was as though I had found myself in some dark alley, danger lurking around the corner and no one to rely on but myself.  I was Chuck Norris in some 80s action movie.  Except without the martial arts skills or unflappable confidence.
</p>

<p>
This exposure came at me in two ways.  
</p>

<p>
First, there were new responsibilities on my shoulders - things that were taken care of for me in my prior life.  I now had to market myself, negotiate my own rates and contracts, accept and also turn down work, and so on.  And this part was a feature not a bug.  I <i>expected</i> that I'd need to do these new things, and in fact it was part of the whole appeal of  me going out on my own.  I'd need to be self-reliant, but in return I could control my terms - what I worked on, when, and for how much - and to not cede control of these things to some other person or entity who was also trying to optimize <i>their</i> best interests.  It was new and stressful to do these things on my own, but I welcomed it.
</p>

<p>
But there was another dimension that I didn't anticipate, and that was the day-to-day exposure.  Right from the start, the things that I was used to doing as a normal part of my job felt a bit different.  I was accustomed to being a consultant, and so my whole approach was already infused with an extra ounce of tact and agreeableness.  But it was different being solo.  Before, I had always had at least a few people on "my side".  Other consultants coding along with me.  Client partners advocating for me.  Project managers backing me up.  Without that team, <b>each and every interaction felt a bit weightier</b>.  Every assignment or task a bit more crucial.  I was more conscious of how I held myself when facilitating a meeting, more aware of every code commit I made, and more vigilant about <a href="https://www.bennorthrop.com/Essays/2022/going-solo-good-and-bad-of-bull-shit.php">being productive always</a>.   
</p>

<p>
Working for a consulting company, there was always some inertia working in my direction.  My small screw-ups or lapses, it always seemed, would just be rolled over by the greater machine, lost or forgotten.  There were people to back me up, or share responsibility.  As an independent though, what I did and what I produced was more directly linked to me and solely me.  There was no cover.  I stood alone.  And this did ratchet up the stress.  
</p>

<p>
So if the exposure, both in big and small ways, increases after going it alone, why do it?  It seems like a net loss.  Here's where there's a silver lining.  
</p>

<p>
As many wise people have said in one way or another, <b>without discomfort there is no growth</b>.  And for me, this has been true.  These new experiences, though stressful, have been a great source of learning.  Before, as a doer, I was never "in the room where it happened", and so never learned how to confidently negotiate, market myself, or navigate tricky account situations.  Now I have some level of comfort with these things.  I've added some business skills to my primarily technical toolbox.
</p>

<p>
There's another layer to this, beyond just the new experience.  As a consultant for someone else, I always gave up a cut of what the client was paying for me in compensation for shielding me from these "exposed" situations.  I'd kick up anywhere from 30-60% to pay for the client partner to negotiate for me, and the accountant to do my invoicing, and the project manager to generally grease the skids.</p>

<p>Often this seemed completely fair - these things were a big help, so I could focus on my work.  But eventually, as I got more experience, this cut that I surrendered to someone else to do these "businessy" things seemed incommensurately large relative to how much effort they took.  If someone helped me land a new contract, it made perfect sense to kick up a large chunk of my bill rate.  But then when I got extended for a 2nd year, why was I still giving away 40% of my bill rate to that person who only helped in the beginning?  Basically, there was a tangible cost to being shielded from these "exposed" business situations, and now that I'm on my own, I don't need to pay that cost, and it's nice.
</p>

<p>
So in the end, there absolutely was an initial bump in stress and discomfort with the new level of exposure.  And, admittedly, I did drop a few balls and maybe even burned a bridge or two as I got my feet underneath me.  But I've appreciated the confidence I've gained through these experiences, knowing that I can now handle myself in a few of those dark alleys.  
</p>

<p>
<i>This is part 2 of a series.  Read part 1, <a href="https://www.bennorthrop.com/Essays/2022/going-solo-good-and-bad-of-bull-shit.php">The Loss of Bullshit</a>.</i>
</p>
				]]>			</description>
			<pubDate>Fri, 15 Apr 2022 00:00:00 -0400</pubDate>
			<guid>https://www.bennorthrop.com/Essays/2022/going-solo-dark-alleys.php</guid>
		</item>
		<item>
			<title>Going Solo and the Loss of Bullshit</title>
			<link>https://www.bennorthrop.com/Essays/2022/going-solo-good-and-bad-of-bull-shit.php</link>
			<description>
				<![CDATA[				<p>
As a full-time employee, I used to loathe "bullshit".  Any time I had to do something that didn't directly help move my project along, it just made me antsy.  And unfortunately, as I saw it, bullshit was everywhere.  There were the company meetings, and the HR training courses, and the checkpoints with the manager, and the "volunteer" work on corporate initiatives, and on and on and on. (<a href="#note">*</a>)  In a given week, bullshit could easily eat up 20-40% of my time.  It used to drive me nuts.  
</p>


<img class="content-image" src="http://www.bennorthrop.com/Essays/2022/meeting-frustration.jpg" width="250" />
<p>
Then I went <a href="https://highlinesolutions.io">independent</a>, and all the bullshit just vanished.  Poof.  Now, my work hours are totally optimized.  Everything I do, whether it's coding,  or collaborating, or researching, is all "productive", in the sense that it contributes in some practical way to the project I'm working on.  And so without a doubt, I get way more done now.  
</p>
<p>
In addition, I find that I also enjoy the work more, because I thrash less.  As a full-time employee, bullshit would be just randomly scattered across my calendar, and so every day would be a non-stop context-switch between bullshit and productive work.  I'd come out of some useless meeting and then frantically try to squeeze in an hour of real work before I had to get to my next bullshit activity.  Now, I have longer blocks of focus time where I can sink into the "zone" and do <a href="https://www.calnewport.com/books/deep-work/">deep work</a>, and it is nice.
</p>

<p>
So for someone who generally enjoys their work, all this is pretty freaking great.  
</p>

<p>
But I've come to realize <b>there is also a flip-side</b>.  Although bullshit is, well, bullshit from a productivity standpoint, it can sometimes be kind of nice from a personal perspective.  Like a pressure release valve.  After a few straight hours of coding, for instance, when I had effectively depleted my <a href="https://www.bennorthrop.com/Home/Blog/2007_12_17_unkempt.php">mental reservoir</a>, sitting in on the quarterly meeting and listening to some exec talk about corporate financials could actually be a relaxing switch-up.  A chance for my brain to take a break, and focus on something different.  Or to just generally space out.  
</p>

<p>
Bullshit could also be a forcing function to do something that benefited me in the long term - like networking or learning some other part of the business.  Although in the moment it seemed like a distraction to my immediate goal, in hindsight, I can see that there was a little bit of value there for me.
</p>

<p>
And so some days, I have to admit, I lament my loss of bullshit.
</p>

<p>
Now of course at this point you might want to shout back: "you're an independent for god's sake, you can do whatever bullshit you want, whenever you goddamn want to!"  And technically that's true!  The big difference, though, is that <b>bullshit is now on my dime</b>.  Because, by definition, bullshit is not tangibly productive, it's not something I can bill a client for.  And so there's now an opportunity-cost to bullshit.  Every hour of it that I do is an hour I'm not making money.  
</p>

<p>
And so given this financial reality, combined with my original antipathy toward bullshit, it made it so, at least in the beginning, I would hardly ever opt for it.  Eventually though a bit of productivity fatigue set in, and I realized some level of bullshit was actually healthy.  So I came up with a few guiding principles to balance things out.  
</p>

<p>
First, since I no longer get paid for it, I realize that I should at least get to choose what type of bullshit I want to do.  So if what I actually need is a mental break, I just go mountain biking, which is way more rejuvenating than a company meeting, in my humble opinion.  (And of course I realize mountain biking is a hobby and not bullshit per se, but that's kind of the point.)
</p>

<p>
Second, I try to frame it differently, and less rigidly.  Some of those things I considered bullshit before, I now see as a type of investment in myself or my business (maybe even a bit like <a href="https://www.bennorthrop.com/Essays/2021/always-do-extra.php">Extra</a>).  So for example, while an hour of browsing tech blogs or a random zoom connect with a former colleague might not immediately help my project, it can be a good way or to learn, to network, or just to be a human being, and so I deliberately try to make a little time for it, and not stress that I billed 7 hours instead of 8 that day.
</p>

<p>
In the end, I found that even bullshit has tradeoffs.  While I do enjoy my current lack of it, that doesn't mean I don't sometimes miss an informal one-on-one with my boss or a random celebration.  I will say though, I have not once missed those HR training courses.  
</p>


<p>
<a id="note">--</a><br/>
<i>* I realize that the things I'm calling "bullshit" are often valuable activities from the organization's perspective.  Regulations that stipulate employees take certain trainings are real.  Meetings that inform all employees of the state of the business are important.  And so on.  But from the perspective of the person who just wants to build quality software (or whatever their immediate job is), these things can end up feeling like a distraction.  Like bullshit.
</i>
</p>				]]>			</description>
			<pubDate>Tue, 15 Mar 2022 00:00:00 -0400</pubDate>
			<guid>https://www.bennorthrop.com/Essays/2022/going-solo-good-and-bad-of-bull-shit.php</guid>
		</item>
		<item>
			<title>Code Ownership, Stewardship, or Free-for-all?</title>
			<link>http://bennorthrop.com/Essays/2022/code-ownership-stewardship-or-free-for-all.php</link>
			<description>
				<![CDATA[				<p>
As the pendulum has swung from <a href="https://microservices.io/patterns/monolithic.html">monoliths</a> to micro-everythings - services, front-ends, you name it - we find ourselves with more "things" to build and maintain.  And so it begs the question, who is responsible for what? 
</p>

<p>
As a simple example, imagine a small team of, say, 6 developers:
</p>

<p class="indentableSubtle">
The team has created and now supports a mobile app, an Alexa skill, three separate web apps, fifteen microservices, and a partridge in a pear tree.  

<br/>
<br/>
And while they've managed to enforce some level of standardization across the ecosystem, by the very nature of modern software development, it's just a lot.  There's Python, Django, DynamoDB, S3, React, Typescript, Tailwind, Swift, and much more, all working together to implement user interfaces, APIs, data persistence, integrations, and so on.  
<br/>
<br/>
Too much for any one developer.  
<br/>
<br/>
Moreover, each sprint comes with different demands for enhancements and fixes, and the work is rarely distributed  equally across the codebases.  One sprint might require heavy changes in the mobile app, and the next might need mostly back-end work.   
</p>


<p>
So again, the question is: how is a team best deployed to fulfill the demands of the business, sprint-after-sprint?  In other words, <b>how do we best divvy up responsibilities</b>?  
<p>

<p>
For example, do we encourage <i>specialization</i> - say, assign Emily to handle all the mobile development, let Joe own the web components, and so on?  And beyond just tech stack, if we have over a dozen microservices, do we draw some boundary around them, and say Javier owns microservices A and B, Anna C and D, and so on?  But what happens when work in their specific area is light for a few sprints in a row?  Are we comfortable with them having a little idle time?
</p>

<p>
Or do we try to better optimize <i>utilization</i>, and encourage a more full-stack, cross-domain culture?  Each developer does it all!  But wait...is this reasonable?
</p>


<h3>Drivers</h3>
<p>
Just like when building software, before we jump to a solution we should <a href="http://www.bennorthrop.com/Essays/2018/unfolding-the-architecture-first-ask-questions.php">step back try to figure out what we're trying to solve</a>.  I'd argue, there are four big things to consider when thinking about developer responsibilities and ownership: 
</p>

<ol class="spaced">
<li>The obvious thing is <b>productivity</b>.  All things being equal, we would like to structure the team in a way that maximizes the work they get done.  I mean, this <i>is</i> why we're paid!  And so optimizing productivity typically means keeping some consistency for developers, aligning their work with their skill-sets and experience.  For example, if Emily worked on the mobile app last sprint, she should be able to knock out that next feature faster than, say, the developer who has been working in the backend.
</li>

<li>
We also want to be mindful of <b>quality</b>.  And similar to above, it's likely that the developer with more hands-on experience in a given codebase will also implement the next feature with higher quality than the one who was parachuted in for one sprint only and doesn't know the structure, patterns, or conventions.  Even the best developers can write crappy code when they don't understand the codebase.
</li>

<li>
Here's where it gets tricky though.  The organization often also needs to mitigate the <b>risk</b> of a developer leaving, and with it their knowledge.  And this often runs counter to the goals above.  Whereas assigning one single mobile developer to all the mobile development sprint after sprint might maximize both productivity and quality, it puts the organization in a precarious position when that developer starts getting texts from the Meta recruiter.
</li>

<li>
Finally, we can't ignore the less-tangible dimension of developer <b>happiness</b>.  But this too is complicated.  Some of us like variety and newness, and so if we're stuck with the same system sprint after sprint, it could affect our productivity or make us more likely to jump ship.  Others prefer predictability and take pride in having their own turf.  Bouncing around would drive them crazy.  In other words, each of us is different, but ensuring that we're fulfilled and challenged is important.
</li>
</ol>

<p>
Now assuming these are the right factors to consider, the crux then is that every organization has to choose its "weights" for each.  What's most important to optimize?  Maybe there's some time-critical force (deadline) at play, and productivity needs to be optimized above all else.  Or maybe the <a href="https://blog.pragmaticengineer.com/advice-for-tech-workers-to-navigate-a-heated-job-market/">market for developers is so hot</a> that the most important thing is just keeping developer happy, productivity be damned!  In other words, it's very much context-dependent.  
</p>

<p>
Hand waving over the "how" here, and assuming the organization knows what it's trying to optimize, it needs to pick some model for structuring responsibilities for the team. But what are the options?  Here are a few of the popular models I've come across:
</p>

<h3>Ownership</h3>
<p>
Often, we settle on a strategy of <a href="http://www.bennorthrop.com/Essays/2010/collective_code_ownership.php">code ownership</a>.  Sometimes it's tacit - everyone just respects that Joe usually does the web stuff, Emily does mobile development, I do the payment microservices, and so on.  Other times it's formalized - management hired Joe as The Web Developer, Emily as The Mobile Developer, and so on.  In either case, in practice it plays out similarly. When new features or fixes come in, we divvy it all up according to what we "own".  This allows us to be maximally productive (in an individual sense), and also increases quality (usually). 
 There are a few downsides however.  
</p>

<p>
First knowledge of different systems can be hoarded, representing a huge risk if someone "wins the lottery"/"gets hit by a bus", as they say.  Additionally, "ownership" can sometimes feel like a shackle to developers, if what they want to be doing is learning new things.  Lastly, it must be noted that while individual productivity increases (since the developer knows their codebases well), collective productivity often decreases with ownership.  As discussed above, because work loads don't cleanly balance out each sprint, this can lead to a feast and famine situation for the owning developers.   For example, one sprint there's more work in their codebase than the owner can handle causing big bottlenecks (or late nights!), and the next month there's not much to do, and that owner is more or less idle.
</p>

<h3>Free-for-all</h3>
<p>
When an organization feels some of these pains of ownership, they often abandon any strategy at all and just wing it: i.e free-for-all.  This system is as simple as it sounds.  A manager sees a pile of work over there, and says "hey you, code-person, get after it!"  And that's that.  
</p>

<p>
While this strategy does ensure that we balance our overall allocations (i.e. Emily the mobile developer isn't idle when there's no mobile work, because she gets pulled over to work on the Python service), this model can be both exhausting and fraught with quality issues.  If we don't have any long-lasting connection to the codebase we're working in, our work is guided only by expedience and ignorance.  We shoe-horn a janky short-term fix in because either we didn't know any better, or because we don't really care much - we'll be in a different codebase next sprint!  As they say, "no one has ever washed a rental car".
</p>

<p>
The free-for-all model is often driven by management who idealistically sees us as interchangeable handymen (i.e. the <a href="https://worthwhile.com/insights/2019/09/05/myth-full-stack-developer/">mythical Full Stack Developer</a>) - quickly able to tackle with grace and ease any technical challenge, no matter what tier, system, or business domain.  And of course this is bull-shit.  For all but the most trivial systems or all but the most exceptional developer, there is too much complexity to be able to navigate our way through <i>everything</i> without proper time to ramp-up.  
</p>

<h3>Stewardship</h3>
<p>
Now somewhere in between these two extremes of ownership and free-for-all is a model of stewardship (or custodianship).  Similar to ownership, developers look after certain codebases where they have the most expertise - they probably did most of the initial work in the project, and their name is all over the code, but they're not responsible for doing <i>everything</i>.  At the least though they must be consulted on changes and be pulled in to triage production issues or discuss design changes.
</p>
 <img class="content-image-left" src="http://www.bennorthrop.com/Essays/2022/trail-steward.jpeg" width="250" />
<p>
This allows for, say, Emily to go over and jump in and give Joe a hand with the web portal when the workload there is high, but to return to her mobile app when things die down.  In other words, it balances both individual and collective productivity.  Additionally, this model also can balance nicely risk mitigation and developer happiness, as developers build some level of familiarity with other pieces beyond their own (i.e. get to learn new things).
</p>

<p>
The important thing with stewardship is that, while it's less formal that ownership, it is still explicitly defined and held to.  At a minimum, a few things should be in place.  There should be a list that defines who is steward of what, GitHub (or whatever SCM tool) should be configured so that stewards must approve all pull requests, and stewards should be given enough allocation (time) to do the necessary "stewarding" of their component.  Unless there's some formality and discipline around this, everything will just slide down the slippery slope until you find yourself in the pit of the free-for-all.  
</p>

<h3>Conservatorship</h3>
<p>
Lastly, it's probably important to also recognize a model that's very popular in <a href="http://www.bennorthrop.com/Essays/2019/programming-at-a-big-company.php">bigger organizations</a>, and that's what I'll call conservatorship.  This is the idea that there is a chosen few  (usually <a href="https://www.joelonsoftware.com/2001/04/21/dont-let-architecture-astronauts-scare-you/">astronaut architects</a>) who have the responsibility of "owning" everything.  They hold the knowledge, make the important technical decisions, and design the business logic/structure, but the actual down-and-dirty work is done by whichever developer is available, usually in free-for-all type of way.  
</p>

<img class="content-image" src="http://www.bennorthrop.com/Essays/2022/astronaut-architect.jpg" width="250" />
<p>
In theory, this model works great.  Efficiency and quality are optimized by virtue of conservators sharing their "wisdom" with the hands-on developers, thereby clearing the path to the quick and effective solution.  And with the help of the conservators, developers can just swap in and out of codebases, relying on the conservator to get them up to speed quickly.  That's the idea at least.
</p>
<p>
In practice, it never works out like this.  Conservators, without any hands-on experience, quickly become detached from the on-the-ground technical reality, and often are no real help at all to developers who need to implement some enhancement or fix some defect.  It can take a developer just as long to ramp up, and additionally can be frustrating because they basically cede their autonomy (and creativity) to the conservator who gets to call the shots.
</p>
<p>
Speaking as someone who has played this conservator role, I can attest to how little help I was to the hands-on developer who needed to get real work done within the systems I supposedly "owned".  This model, in my opinion, sucks for everyone - and this is why I try to avoid these types of roles.
</p>

<h3>In Summary</h3>
<p>
In the end, what started in my head as quick post about different models of code ownership went way longer than expected.  This is how I think about it though, and these are just a few models I've come across for divvying up work. I'd love to hear your thoughts and experiences.
</p>

<p>
<i>
* And yes, if you were wondering, I thought of the name "Conservatorship" after watching the Free Britney documentary with my wife. :) 
</i>
</p>
				]]>			</description>
			<pubDate>Wed, 16 Feb 2022 00:00:00 -0500</pubDate>
			<guid>http://bennorthrop.com/Essays/2022/code-ownership-stewardship-or-free-for-all.php</guid>
		</item>
		<item>
			<title>Deleting Data in a Microservices Architecture</title>
			<link>http://www.bennorthrop.com/Essays/2021/microservices-architecture-and-deleting-data.php</link>
			<description>
				<![CDATA[				<p>
For all the <a href="https://martinfowler.com/articles/microservices.html">advantages of microservices</a>, there seem to be just as many new complexities and complications.  One scenario I've hit a lot recently (and haven't found a lot of great resources on) is that of deleting data.  Consider a simple example:
</p>


<p class="indentableSubtle">
There are three services: a <i>Product</i> service which manages data related to products offered, an <i>Order</i> service which tracks purchases of products, and a <i>Catalog</i> service which controls what products are published to different mediums (say, print, digital, etc.).  
</p>


<p>
Now what happens if a given product needs to be deleted?  Say "Widget X" is no longer a product to be sold.  Or "Widget X" was accidentally added by some sleepy user, and just needs to be removed.  What's the best way to handle this?
</p>

<h2>Solution 1: Just Delete It</h2>
<p>
In a monolith world, we might be able to just delete the "Widget X" row in the <code class="inline">PRODUCT</code> table and that would be that.   If there was some foreign key reference to that product row from some row in another table (e.g. because the product was sold in a prior order, or the product was included in an existing catalog), there could either be a delete cascade that would automatically remove those rows too (often a dangerous thing), or at least there would be some foreign key constraint that would throw an error when trying to delete that product.  Either way though, because all the data in a monolith resides in one database, the management of referential integrity (i.e. not leaving orphaned data) could be centrally managed.  
</p>

<p>
In a microservices architecture, this obviously <a href="https://stackoverflow.com/questions/44870461/microservices-how-to-handle-foreign-key-relationships">doesn't work</a>.  Sure, the "Widget X" row could just be thoughtlessly deleted from the <code class="inline">PRODUCT</code> table in the Product service, but other services would then have data that's effectively orphaned.  
</p>

<img src="http://bennorthrop.com/Essays/2021/Microservices-Data-Deletion-Ref-Integrity.png" style="display: block; margin-left: auto; margin-right: auto;" class="mobile-wide-image" align="center"/>

<p>
For example, the Order service might have a reference to "Widget X" in its <code class="inline">ORDER_DETAILS</code> table for an old order, and might want to fetch information on this product to show full order details.  If "Widget X" was deleted from the Product service, the Order service would get a 404 on its GET request for <code class="inline">/products/widget-x</code>.  In other words, even though each microservice is intended to be de-coupled and autonomous, it doesn't mean that it's completely independent from a data perspective.  Coordination and communication is necessary if we want to preserve some level of referential integrity.
</p>


<h3>Solution 2: Synchronous Coordination</h3>
<p>
The next possibility is to have the Product service, on delete of a given product, first check with any dependent service to see if it's able to delete that product and then to carry out that "cascade" if necessary.  For example, the Product Service could first check with the Order Service and Catalog Service if it's safe to delete "Widget X" (i.e. there are no references to it), and only on confirmation that it's safe would it do its delete from the <code class="inline">PRODUCT</code> table.  Or alternatively, the Product Service could go forward with its own delete and then make a synchronous call to the Order and Catalog Services, and say "I just deleted my Widget X, so delete any reference to it from your databases".  
</p>

<img src="http://bennorthrop.com/Essays/2021/Microservices-Data-Deletion.png
" style="display: block; margin-left: auto; margin-right: auto;" class="mobile-wide-image" align="center"/>


<p>
Even if deleting this way was ok from a business rule perspective, this also is ill-advised.  Creating a synchronous dependence from the Product Service to the Catalog and Order Services has major downsides -  an increase in complexity, additional latency per request, and compromised resilience/availability (i.e. if the Order Service was down, the Product Service couldn't do a delete).  Microservices should strive to be as independent as possible. Binding them together with runtime dependencies should only be done with great consideration, lest we just create a <a href="https://www.gremlin.com/blog/is-your-microservice-a-distributed-monolith/">distributed monolith</a>.  
</p>

<h3>Solution 3: Just Don't Delete</h3>
<p>
At this point, we might observe that it doesn't really make sense to delete a product anyway!  As <a href="https://udidahan.com/2009/09/01/dont-delete-just-dont/">Udi Dahan points out</a>, in the real world there really isn't a notion of "deleting" things.  Instead, the data just changes state.  Employees aren't deleted, they're fired or they quit.  Orders aren't deleted, they're cancelled.  And Products aren't deleted, they're no longer sold.  In other words, in almost all cases, it's better to support some status field on a given row than to outright delete it.
</p>  

<p>
In the example here then, this would solve some of the problems.  Instead of supporting a true "delete", the Product service would just expose a "decommission" (or whatever) endpoint for a product, but preserve the data in its database.  In this way, the Catalog and Order Services would no longer have orphaned data - they could both still call back to the Product service to get information on "Widget X", even if it's no longer currently sold.  
</p>

<p>
But this doesn't solve everything.  What if the Catalog Service needs to be aware of a Product being decommissioned, so that it doesn't get shown to a customer for a given catalog?  Sure, it could query the Product Service to get this information, but this could introduce a synchronous dependence from the Catalog Service to the Product Service, and introduce those same issues of complexity, latency, and resilience discussed above.
</p>

<h3>Solution 4: Asynchronous Update</h3>
<p>
To support the Catalog Service's autonomy, instead of relying on the Product Service it could maintain its own local cache of product data, keeping it sync with changes from the Product Service.  When a product is decommissioned, the Product Service could emit a <code class="inline">ProductDecommissioned</code> event which the Catalog Service would listen for, and then it could update its own local product store.  In the case of "Widget X", as soon as it was decommissioned, the Catalog service could know to not show it in its catalog.  And this works.  Except...
</p>

<p>
What exactly <i>is</i> this local cache of product data?  Is it in-memory?  Or a table in the Catalog Service's database?  And how do we make sure it's in sync with the source of truth, the Product Service?  There are a few options here, each with its own pros and cons.  
</p>

<p>
If the local cache is in-memory, then this is light weight to implement, and potentially easy to synchronize (e.g. maybe there's some reconciliation process that checks the Product Service and ensures that its own data is fresh/up to date).  The downside is that it gives up database-level referential integrity.  If there's some product_id in a <code class="inline">CATALOG</code> table in its database, there would be nothing to enforce (at a database level) that that product_id is in fact valid (i.e. maps to a product_id in the Product Service database).  Additionally, the in-memory cache may not tenable if the data to be cached is large.
</p>

<p>
Alternatively the local cache in the Catalog Service could also be a database table, which would solve the database-level referential integrity and storage issues from above.  One problem though is complexity.   Writing the SQL to seed and update a local <code class="inline">PRODUCT</code> table is not trivial - more code written means more code to maintain.  Additionally, there's added complication around the synchronization - if there are multiple instances of a given microservice, but only one database instance, which microservice or what process is responsible for updating and synchronizing the cache?  
</p>

<p>
Probably the better solution is to <a href="https://blog.twitter.com/engineering/en_us/topics/infrastructure/2020/deleting-data-distributed-throughout-your-microservices-architecture">implement an Event Log</a> (using Kafka, etc.), and let each microservice leverage this to keep in sync with changes to data.  There is so much to consider with this option (way beyond the scope of this blog post), and a great place to start is <a href="https://www.amazon.com/Building-Event-Driven-Microservices-Leveraging-Organizational/dp/1492057894">Event Driven Microservices</a>.  While this pattern elegantly solves all of the problems above, this is, in my opinion, a level-up architecture, both to build and support, and so only something to jump into without adequate expertise and resources.  
</p>

<p>
In conclusion, though I know this doesn't fully settle the issue on deleting data within Microservices, my hope is that it did highlight some of the salient issues and options.  Please comment below with any tips or feedback!
</p>
				]]>			</description>
			<pubDate>Fri, 05 Nov 2021 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2021/microservices-architecture-and-deleting-data.php</guid>
		</item>
		<item>
			<title>Always do Extra</title>
			<link>http://www.bennorthrop.com/Essays/2021/always-do-extra.php</link>
			<description>
				<![CDATA[				<p>
With all the <a href="https://medium.com/teklit/coding-is-a-trap-get-out-14a6beb28c8">stresses and demands</a> of development that seem to send <a href="https://whoisnnamdi.com/never-enough-developers/">many of us to the exits early</a>, how is it that some stick around?  What's the secret to longevity in this career?  
</p>

<p>One thing I've noticed over the years is that there <i>is</i> at least one thing that seems to be common to every good, veteran programmer I know.  They all follow the same deliberate and dare-I-say selfish rule to how they approach their time: <b> Always do Extra</b>.  Now before you call "bullshit", let me explain what I mean...
</p>

<p>Assume there's a reasonable amount of work you need to do to fulfill the base expectations for your job (i.e. your Normal Work) and then there's a little time left over.  (I know some may argue this "left-over time" thing, but just go with me).  In this remainder time you have a choice: you can do More, Extra, or Nothing (i.e. surf the interwebs).  And it's with this decision that every reasonably happy, veteran developer I know distinguishes themselves.  They all choose Extra. 
</p>

<img src="http://www.bennorthrop.com/Essays/2021/AlwaysDoExtra.png" style="display: block; margin-left: auto; margin-right: auto;" class="mobile-wide-image" align="center">


<p>
But aren't More and Extra the same thing?  No! They sound similar, but they're actually very different.  Here's a simple example:  
</p>

<p class="indentableSubtle">Say for this sprint you're assigned two form screens that take user input and then persist it to the database.  Pretty straight-forward.  This is your Normal Work - the default expectation of what you need to get done to be in good standing on your project.  
</p>

<p>
Doing More would be completing those two screens and then taking on a third screen that's just like it.  Yes, this would help move the project along faster and make your manager happy, and that's great, but in the long-run, More doesn't give <i>you</i> much.    
</p>

<p>
Extra is different than More.  Extra is finishing those two screens, but then researching a new library for form validation that might reduce the boilerplate code.  Or it's learning ways to protect against common security vulnerabilities from data entry.  These little off-ramps from the main highway of Normal Work <i>could</i> be dead-ends and not have any practical value to the project.  But they might also be important contributions.  And that's the thing with Extra.  While the tangible value to the project is uncertain (it could be nothing this time or it could be something), <b>the value to <i>you</i> is real</b>.  
</p>

<p>
Extra gives back in a couple ways. The first is philosophical.  Extra is about having free will.  It's about not being just a drone who monotonously does exactly what their told, but someone who asserts a little control and shapes their our own contributions and experiences in a way that's interesting or meaningful.  
</p>

<p>
More practically though, Extra is also good for our careers.  Our employability has everything to do with the diversity and depth of our experiences, and so Extra is what helps us broaden ourselves beyond just what's useful on our narrow project.  Whereas grinding it out to finish that third screen wouldn't add any new skill or insight to our toolset, a little bit of exploration from Extra could.
</p>

<p>
Now there are of course caveats.  Over the years I've seen developers get carried away with Extra.  Extra is all they want to do.  They spend their days researching new validation frameworks or security vulnerabilities, and then can't get their Normal Work done, those two basic screens.  And sure this might be more fun for them, but it sucks for the rest of us because we have to pick up their slack if we want to deliver the project on time.  So there are rules to Extra.  
</p>

<p>
The first rule is this: <b>Extra must be balanced against Normal Work</b>.  Real stuff still needs to get done.  This is how we get paid.  Shirking our Normal Work in favor of Extra might be more interesting, but it makes us shitty teammates at best, and unethical at worst.  <i>Note: there are a few "lucky" among us who find their way into roles where Extra is their Normal Work, and we call these people Architects. ;)</i>
</p>

<p>
The second rule of Extra is that <b>it must be aligned</b> with your Normal Work.  If what's on your plate is two form screens, Extra can't be learning about evolutionary algorithms or building a mobile app for your side hustle.  It's got to be something that could help the project.  It's never something we need to hide, but instead it's something we're eager to share with our teams - ala "hey, I did some research on X, and maybe this is something that could be valuable for us to try".  
</p>


<p>
In the end, I hope it's clear that I'm not arguing that we neglect our Normal Work.  This is what is expected of us, but the choice is what we do beyond this: Nothing, More, or Extra.  In my experience, those who have had longevity in this field always choose Extra.  I'd love to hear your thoughts.      
</p>

				]]>			</description>
			<pubDate>Wed, 13 Oct 2021 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2021/always-do-extra.php</guid>
		</item>
		<item>
			<title>A Better Resume for Developers</title>
			<link>http://www.bennorthrop.com/Essays/2021/techrez-a-better-resume-for-tech.php</link>
			<description>
				<![CDATA[				<p>
It's 2021 and we have LinkedIn and Indeed and a ton of other apps, services, and algorithms to help us find employers and to help employers find us.  But yet we still have resumes.  And they still kind of suck.  
</p>

<p>
Of course they're not as central to the process as they were years ago, but <i>some</i> companies still use them to help decide who to interview, and <i>some</i> interviewers still use them as a guide for what questions to ask.  And in either of these scenarios, if you're the one who has to read through the resume, it's not a great experience.
</p>
<a href="https://techrez.io/resume/andrew-lu"><img src="https://techrez.io/images/ss-ben-2.png" align="right" width="250" /></a>

<p>
The problem is our typical developer resume is a multi-page chronicle of every system, component, and library we've ever worked with over the course of our entire careers.  Information overload.  If the reader had only a few minutes to skim our resume (which is usually the case), it'd be really hard for them to come away with an accurate picture of what we know or what we've done.  They might wonder, "how much has he worked with single page apps?", and then would scan the resume like a grade school word search until their few minutes were up.</p>

<p>
But it makes sense why it's this way.  From a developer's perspective, it behooves us to cram in as much information as possible, lest we miss out on conveying some skill we've honed or technology we've used that might be relevant to some company.  It's like packing for a month-long vacation where you don't know whether you'll be skiing, sunbathing, or going to a formal dinner. Might as well pack it all! And so our resumes become absurdly long.  
</p>

<p>
My goal with this project was to improve on that user experience, even if just a little.  Make the resume more of an interactive dashboard than a static document - one that allows us to keep all the detail, but lets the reader zoom in and out to view what's most interesting.  So given this guiding vision, I built two main features for the MVP:
</p>

<p>
First, there's a <b>timeline view</b> at the top, so the resume reader can quickly get the "big picture" of your career trajectory.  How long have you been different places?  Have you been going to school and working at the same time?  How long have you been a "senior"?  In my opinion, seeing this visually makes this way easier.
</p>

<a href="https://techrez.io/resume/andrew-lu"><img src="/Essays/2021/techrez-ss-timeline.png" class="mobile-wide-image" /></a>

<p>
The second feature is a full-resume <b>skill filter</b>.   Each experience is tagged by skill, and then these skills can be used to filter the resume content.  So if you want to see how much I've worked with NodeJS, then clicking on "NodeJS" would filter the entire resume down to only those experiences where I used it.  
</p>

<a href="https://techrez.io/resume/andrew-lu"><img src="/Essays/2021/techrez-ss-filter.png" class="mobile-wide-image" /></a>

<p>
There are a few other bells and whistles that hopefully make this a viable way to maintain and share your resume, like PDF download and custom themes, but that's the gist of it as of now.
</p>

<p>
I have no idea whether this will fly, but it's been fun working on it.  Give it a try at <a href="https://techrez.io">TechRez.io</a>.  And if you have any feedback or ideas, I'd love to hear it either in the comments below, or you can <a href="https://techrez.io/contact">send feedback</a> on the site.
</p>				]]>			</description>
			<pubDate>Mon, 26 Jul 2021 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2021/techrez-a-better-resume-for-tech.php</guid>
		</item>
		<item>
			<title>What do we Mean by Rewrite and Refactor?</title>
			<link>http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-1-what-we-mean-by-rewrite-and-refactor.php</link>
			<description>
				<![CDATA[				<section id="setup-blurb">
This is chapter 1 of a mini-book I recently started on the topic of <a href="http://www.bennorthrop.com/rewrite-or-refactor-book/index.php">rewrite or refactor</a>.  Progress is slow, but steady.  Feedback welcome!
</section>

<p>
We're ready to start our journey.  We have an application that's riddled with technical debt, woefully out of date, or just generally underserving its users, and so we need to understand what our best option is going forward - does it make more sense to continue to plod along and incrementally refactor?  Or do we blow it all up and rewrite from scratch?  This is the basic dilemma we'll be exploring in <a href="http://www.bennorthrop.com/rewrite-or-refactor-book/index.php">this book</a>.  So let's get going...
</p>

<p>
But not so fast!  Before we go any further we need to address the elephant in the room, which is this: for any legacy application in need of improvement, <b>what to do next is not a simple this-or-that decision</b>.  We may frame our options generally as <i>rewrite</i> or <i>refactor</i>, but these terms, as we'll see, are really just stand-ins for a whole spectrum of choices that lie before us.  
</p>

<img src="http://www.bennorthrop.com/rewrite-or-refactor-book/Rewrite-Refactor-Spectrum.png" style="width: 80%;  display: block; margin-left: auto; margin-right: auto;" align="center">

<br/>
<br/>
<p>
By refactoring, within the context of modernizing a legacy application, we typically mean that we're going to keep the application mostly as it is, but make some minor, internal improvements to solve specific problems (like maintainability, extensibility, etc.).  By rewriting, on the other hand, we imply that we intend to "start again from scratch", or in other words to make major changes.  
</p>

<p>
But this only begs the next question!  What exactly do we mean by <i>minor</i> and <i>major</i>?  If we plan to upgrade our frontend framework from AngularJS to React but keep the backend services as they are, is that a refactor or rewrite?  Or what about if we want to break a monolith into three different microservices, but the business logic is just copied-and-pasted into new version-control repos - is that a rewrite, refactor, or something else?  And do we even care?  Does labeling our effort really matter?
</p>

<p>
Yes, it does.  Although our job is to build working software and not philosophize about semantics, the words we use <i>do</i> make a difference.  When we suggest the path of rewriting or to refactoring, business and technology stakeholders should understand exactly what we mean and what type of effort will be entailed.  In other words, some <b>precision in our terms will help us better set expectations</b>.  Further, as we burn through some of this conceptual fog and find clearer definitions, it will also give us a more nuanced view of this decision, and move us beyond the narrow <i>rewrite or refactor</i> framing.  
</p>
<p>
So like any big journey, let's spend a little time packing before we jump in the car and go.  We don't want to show up at the beach and realize we forgot our swim suit.  
</p>


<h2>Functional Improvement</h2>
<p>
A good place to start is to define what rewrites and refactors are <i>not</i>, which are strategies to improve the functionality of an application.  This type of work, whether it's fixing defects, delivering new features, or cleaning up the user interface, we can call enhancement.  It's about improving on what the application <i>does</i> for its users, and as we'll see later, it's the normal state of development.  
</p>
<img src="http://www.bennorthrop.com/rewrite-or-refactor-book/Rewrite-Refactor-Functional.png" style="width: 30%;  display: block; margin-left: auto; margin-right: auto;" align="center">
<br/>
<br/>
<p>
In some cases, the scope of the functional enhancements can be quite large though.  The business may determine that the app serves the right user base, for example, but the features all need to be overhauled.  It may be tempting to call this case a rewrite as well, however we're going to make a distinction here.  Because this type of effort entails building <i>all</i> new functionality, it is basically indistinguishable from greenfield development.  When new functional requirements need to be defined, a separate system is developed from scratch, and no carry over of logic or code is possible, we will consider this to be development of a greenfield app and not a rewrite.  
</p>



<h2>What we mean by Refactoring</h2>
<p>
Adding functionality to an application is not what this book is about. Our situation is that the application generally does <i>what</i> it is expected to do, but is lacking in the <i>how</i> - in other words, the non-functional or <a href="http://www.qasigma.com/2008/12/software-quality-attributes.html">quality attributes</a> of the system.  For example, users might be happy with the set of features, but the application might be excessively difficult to maintain, or it may crash frequently, or may perform poorly under peak load.  It's when these non-functional attributes are lacking that we consider a rewrite or refactor.  
</p>
<p>With respect to refactoring, we often use this term to refer to different scopes of work. In his book <a href="https://martinfowler.com/books/refactoring.html"><i>Refactoring</i></a>, <a href="https://martinfowler.com/">Martin Fowler</a> defines it this way:
</p>

<p class="indentableSubtle">
Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior.
</p>

<p>
In this purist sense, refactoring is primarily about making the code more maintainable.   This might be decomposing long or complex functions, fixing inconsistent naming, adding unit tests, or restructuring class hierarchies, data structures, or schemas.  Note that nothing that is <i>visible</i> to the user changes, but the internal code structure is modified to make it easier to work with for developers, thus improving our productivity (and happiness!).   
</p>

<p>
In the context of our rewrite or refactor decision, however, this definition is too restrictive.  When we talk about refactoring in this context, we're not typically making a distinction between internal and external, but rather about <b>functional and non-functional</b>.  For example, we may say that we are choosing to refactor the existing code base to improve the reliability or performance of the application.  These non-functional attributes are technically not <i>internal</i> properties of the system (they are very visible to the users in that they directly impact them), they are just <i>non-functional</i>.  This might be a pedantic distinction, but in the spirit of precision, I think it's important to call out.   In this book we'll be using a broader definition of refactoring:
</p>

<p class="indentableSubtle">
Refactoring is an approach by which an existing body of code is incrementally restructured in order  to improve the non-functional attributes of the system.
</p>

<p>
Lastly, it's important to note that refactoring is about iterative change.  It's making minor tweaks to the application, delivering them, and then rinse and repeat.  Layered in with functional enhancements, refactoring can keep our users happy and our codes base healthy, minimizing technical debt and feature gaps.  When neglected, however, we may need to consider the more heavy-weight alternative.
</p>

<h2>What we mean by Rewriting</h2>
<p>
Like refactoring, rewriting has the same basic goal - to improve the non-functional nature of the application.  The difference is in how much is changed.  Simply put, if refactoring is duct tape, rewriting is a sledge hammer or a back hoe.  It's not about making incremental improvements to what is there, it's about blowing it up and building anew.  With respect to the other types of development efforts we've discussed, we can visualize a rewrite this way:
</p>

<img src="http://www.bennorthrop.com/rewrite-or-refactor-book/Rewrite-Refactor-Quadrant.png" style="width: 65%;  display: block; margin-left: auto; margin-right: auto;" align="center">


<p>
We can say then that a rewrite is an effort that <b>involves major changes to the system in order to make fundamental improvements to its non-functional attribute</b>s.  But there is gray area.  Rewrite efforts often spill over into the other quadrants.  For example, an application may be so crippled by technical debt that it's virtually impossible to add new features.  We may choose then to rewrite  and build a new foundation to improve maintainability and extensibility (non-functional attributes), but during the course of that rewrite we may also sneak in a few new features to satisfy the business.  It's fundamentally a rewrite, but there is some enhancement going on as well.  
</p>
<p>
Likewise, there is some fuzziness at the boundary of rewrite and refactor.  There are lift-and-shift scenarios where the system is moved to a new platform making it essentially a different application, but the code implementation within it is mostly the same - i.e. not refactored.  This feels like a rewrite, but is it?  How much do we have to change to consider it a rewrite?
</p>

<p>Again, let's see if we can add some precision.  For the purpose of this book, let's use the following definition:
</p>

<p class="indentableSubtle">
Rewriting is re-building the same functionality that exists in a legacy application but using a different language/framework, maintaining within a new code repository (not just a branch), and deploying as an entirely new artifact (possibly to a different platform - e.g. servers, hardware, serverless, client, etc.).
</p>

<p>
In other words, we're drawing some clear lines.  If, for example, we're rewriting an important function, class, or even module, but our work is made in a branch off of the mainline of our codebase, it's not a rewrite.  Likewise, if we re-implement a segment of the application, but the system itself is still deployed as the same artifact (binary, WAR, etc.), this also is not a rewrite.  Rewrites within our context are BIG.  They are about major changes that necessitate an entirely new application to be built and deployed.  Yes, there may be incremental steps along the road to get there, as we'll see later, but it is a fundamentally different effort than refactoring.  
</p>

<p>
To help clarify things in your individual case, it can be helpful to diagram this out.  For the different possible paths for modernizing or improving your application, what exactly is being changed?  Here's an example:
<p>

<img src="http://www.bennorthrop.com/rewrite-or-refactor-book/Rewrite-Refactor-Distinction.png" style="width: 60%;  display: block; margin-left: auto; margin-right: auto;" align="center">
<br/>
<br/>
<p>
In practice, the nature of the changes may not line up neatly with the definitions of rewrite or refactor, and that's ok.  The diagram above, for example, might represent a case where we're proposing to re-implement a service using a more modern set of technologies, but while keeping the exposed API and underlying persistence structure the same.  This represents a blend of minor and major changes, so it still may not be clear precisely what to label it.  What's important, however, is that we've arrived at deeper level of detail which will help us better reason about and justify the decision.  
</p>

<p>
Now we're almost done with our preparations, but before we get on with our journey, let's put it all together and see how these different types of development efforts all fit within the lifecycle of a given application.  In other words, let's explore the origin story for a rewrite. 
</p>


<h2>The Rewrite Origin Story</h2>
<p>
It all starts in the <i>Greenfield Development</i> stage, where we take an idea and begin to build from it a functioning application.  After weeks or months of dogged effort, something is eventually <i>Launched</i> to "market" (which may be actual paying customers, or just  a set of internal business users, etc.).  If the app is well received, it lives in the equilibrium stage of <i>Enhancement</i> for some period of time, where new features are added and defects are resolved.  Everyone is happy.  Eventually though, <a href="http://www.bennorthrop.com/Essays/2019/the-trouble-with-tech-debt.php">technical debt</a> can accumulate, and we begin to see <i>Diminishing Returns</i> in our effort - whereas a week of development used to be enough to add an entire new feature, it might barely suffice now to change the color of a button.  
</p>

<img src="http://www.bennorthrop.com/rewrite-or-refactor-book/rewrite-lifecycle.png" style="width: 80%;  display: block; margin-left: auto; margin-right: auto;" align="center" />
<br/>
<br/>

<p>
It's at this point that we might question whether it's worth investing more time and money.  Further, since the app was first launched, some exciting new technologies have probably emerged, and we may have some grand visions for how they could be leveraged to make our app more resilient, easier to work with, performant, etc.  And so we begin to make a plan for a rewrite.  The idea is to freeze development on the existing system for some short period of time, and then shift resources over to work on the replacement system.  We'll first build the foundation (using more modern patterns, tools, languages, etc.) and then next migrate the existing functionality into it.  Users will just need to ride out the "pause" (i.e. not get any new updates), but when the rewritten system is in place, productivity should be twofold (or more!) what it was before.
</p>

<p>
And while this plan seem may seem straight forward, it belies some critical risks - technical, organizational, and psychological factors that all conspire to make this rewrite stage extremely precarious.  And as this phase drags out, our chances making it out with a successful replacement get dimmer and dimmer.  In the next two chapters we'll explore some of these <a href="http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-2-the-risks-of-rewrites.php">dangers lurking</a> within a rewrite effort, and then the reasons why we often <a href="http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-3-why-we-rewrite-even-when-we-shouldnt.php">forge ahead anyway</a> in spite of them.  
</p>

				]]>			</description>
			<pubDate>Mon, 24 Aug 2020 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-1-what-we-mean-by-rewrite-and-refactor.php</guid>
		</item>
		<item>
			<title>The Risks of Rewrites</title>
			<link>http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-2-the-risks-of-rewrites.php</link>
			<description>
				<![CDATA[				<p>
In the <a href="http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-1-what-we-mean-by-rewrite-and-refactor.php">last chapter</a> we drew some clearer lines around the terms <i>rewrite</i> and <i>refactor</i>, defining both as approaches to improve the <a href="https://resources.sei.cmu.edu/library/asset-view.cfm?assetid=513803">quality attributes</a> of an application, but differing in scope. 
 Whereas refactoring is about making incremental changes to an existing system, rewriting is about starting over and building anew.  Rewrites, in other words, are BIG.  And risky.  And yet despite this, there's still a deceptive allure to them.  The logic can go something like this: </p>

<p class="indentableSubtle">
The system is already in production, we obviously know how it works, so we just need to port what we have to a better platform, and once we're there things will be easier.
</p>

<p>In this chapter, we're going to rip this basic intuition to shreds.  Rewrites, as we'll see, are anything but easy.  While they may be immune to some of the challenges of a nascent app, they introduce completely new ones we often don't anticipate.  In order to successfully deliver a rewrite, we must navigate these challenges, and so it's important to understand what they are up front.  
</p>


<h2>Parallel Development</h2>
<p>
The first hazard we often confront on our journey is the realization that a rewrite is fundamentally a dual prong effort.  Sure, on the technology side we'd love to think we can pause development to focus only on writing code in the new platform, but reality (and more specifically, the business) rarely abides.  Maybe in order to win (or keep) an important customer, the business demands we add some new feature to the existing system NOW.  Or maybe a third-party system has changed its API and we need to refactor, or a sev-1 defect pops up, or a new government regulation is written.  The point is, <b>almost never can a production system sit static in space and time for long</b>, and that's true even during a rewrite period.  Some care and maintenance will inevitably be necessary on the old system, which means parallel development.
</p>

<p>
The first problem here is that developing in parallel violates that principle we developers hold most sacred: <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">Don't Repeat Yourself</a>.  Any change made to the legacy system will need to be ported into the new system as well.  For example, if we add feature X into the old stack, we must add X again in the new one (but this time write it in the new language or framework).  And that duplicative effort applies for the testing, project management, build, and deployment of X as well.  Essentially, whatever it would cost (in time or resources) to make a change to the legacy system, it could now, during this rewrite phase, easily cost double.  
</p>

<p>
Even more, depending on how far along the rewrite effort is, the change (e.g. feature, defect fix, etc.) might need to be made to a part of the source code that has not yet been rewritten, and so the team will have to remember and account for it when they get there (which will then push the timeline back for the rewrite).  Or in the opposite case, the change is in a section of the app that has <i>already</i> been rewritten, and so the team has to circle back and make updates to code that was just migrated (and then re-test, etc.).  Either way, the parallel development element of a rewrite can make it feel like the team is keeping a plane flying while also building its replacement on the ground.  For the safety of the passengers, that plane's got to stay in the air, but if we spend too much focusing on its maintenance, we'll never get the new one off the runway.  And of course the team responsible for both "planes" is often one and the same, which leads to the next issue...
</p>

<h2>Team Schism</h2>
<p>
Given that there's some amount of effort necessary to support the existing system, the question is: who is responsible for this?  There are a couple approaches that teams typically take to manage the parallel work.  One option is to have the more junior developers stay back in maintenance mode, and thereby free up the senior devs to forge the path forward for the new system.  And this makes sense.  To pull off a rewrite generally requires a higher level of technical competence - getting new technologies up and running and working together, configuring environments, establishing patterns and conventions, and so on are all tricky tasks that could leave a more green developer spinning their wheels in the mud.  
</p>

<p>
And so teams may settle on this type of split, junior developers to maintain, senior developers to go forward.  And it may work for a short while, but <b>it's not long until the senior devs are pulled back in</b> to help solve a critical all-hands-on-deck issue or discuss the impact of some change.  Their years of acquired knowledge of the old system and their relationships with business stakeholders, ops people, and others make them effectively irreplaceable.  They need to be included.  And even if these "pull-outs" only take up a couple hours a week, that level of context-switching can still stymie productivity.  As developers float back and forth between the old and new systems, the timeline for the rewrite just gets pushed back.
</p>

<p>
To avoid this, teams may take an alternative approach: spin up a new team that can be more easily dedicated to the rewrite.  The developers on this "rewrite team" would have negligible ties to the existing system (maybe they're consultants, new hires, etc.) and would therefore be better able to isolate themselves and stay productive on the new work.  Problem solved?  No.  The first issue, of course, is that these developers are by definition less familiar with the codebase, domain, and generally how and why things work the way they do.  Sure, they have the original code as documentation, but this can be like learning a programming language by looking at the source.  It's all facts, but no story.  And so this new team will either flail while trying to understand the intricacies and complexities of the existing system, or make bad assumptions just to move forward, or end up having to pull in the original team anyway.  None of these are productive outcomes.
</p>

<p>
Additionally, this "fresh team" approach can also alienate the veteran developers who are charged with staying back to support the legacy system, and make them feel as though they are being penalized for their loyalty and experience.  While the new team gets to work with modern technologies and a clean slate, they are still left in the doldrums of maintenance.  No fun.  And so unsurprisingly, this can quickly lead to disgruntled developers and shortly after that, brain-drain.  Somehow a team structure needs to be devised where the old system can be supported, the new system can be built correctly and efficiently, and everyone is happy.  But even when you put the right people on the right busses, there are still surprises...
</p>

<h2>Unknown Unknowns</h2>
<p>
Now even if the rewrite team is staffed with seasoned developers - i.e. those who either helped write the legacy system or at least have some experience with it - there are always surprises when migrating the existing source code to the new platform.  Donald Rumsfeld (yes, <i>that</i> <a href="https://en.wikipedia.org/wiki/Donald_Rumsfeld">Donald Rumsfeld</a>) made this not-so-crazy insight about these types of surprises:  

<p class="indentableSubtle">
Reports that say that something hasn't happened are always interesting to me, because as we know, there are known knowns; there are things we know we know. We also know there are known unknowns; that is to say we know there are some things we do not know. But there are also unknown unknownsâ€”the ones we don't know we don't know. And if one looks throughout the history of our country and other free countries, it is the latter category that tend to be the difficult ones.
</p>

<p>
When we begin the rewrite process, we typically try to estimate how much effort it will be.  And it's here where we begin to catalogue the first two categories of work.  There are of course segments of the codebase that we have direct experience with, and so we give quicker (and more accurate) estimates.  These are the known knowns.  But then there are also pockets of the system that we recognize we have less direct experience with, and so we add a little buffer.  "Joe wrote the registration flow, and he quit last year, so that might take a little longer to migrate".  These are the known unknowns.  And so we proceed with planning, estimating both types of work and giving extra time for the known unknowns, until an overall timeline is agreed to.
</p>

<p>
It's not until we dig in and start migrating code, however, that we stumble upon that third and most pernicious category of work, the unknown unknowns.  It may be a 1,000 lines of convoluted business logic we never knew existed, or a set of reports we didn't know were used by anyone, or some "duct tape" that unbeknownst to us holds an entire integration together.  Whatever it is, our original rewrite plan never took it into account, but we're in too far at this point to bail out.  The result is that this (formerly) unknown unknown will need to be be analyzed ("what the heck does it do?") and then dealt with ("do we need to bring this over, or can we leave it behind?").  And this extra analysis, discussion, and effort just pushes back the initial timeline and strains the patience of business sponsors and customers.</p>

<p>
And while a few of these unknown unknowns can be absorbed, too many can put the entire rewrite effort in jeopardy.  With better planning and decomposition (more on this later), they can be minimized, but avoiding them altogether is difficult.  There is another hazard, however, that we inflict on ourselves...
</p>

<h2>The Second System Effect</h2>
<p>
Often, we've been living with the warts and imperfections of the existing system for so long that when we finally get the chance for a do-over, we can't help but want to make everything better.  Or perfect.  Decades ago, <a href="https://en.wikipedia.org/wiki/Fred_Brooks">Fred Brooks</a> labeled this tendency the <a href="https://en.wikipedia.org/wiki/Second-system_effect">Second System Effect</a>.  In the <a href="https://en.wikipedia.org/wiki/The_Mythical_Man-Month">Mythical Man Month</a>, speaking of the architect of the system, Brooks observes...
</p>

<p class="indentableSubtle">
As he designs the first work, frill after frill and embellishment after embellishment occur to him.  These get stored away to be used "next time."  Sooner or later the first system is finished, and the architect, with firm confidence and a demonstrated mastery of that class of systems, is ready to build a second system.
<br/>
<br/>
This second is the most dangerous system a man ever designs.  When he does his third and later ones, his prior experiences will confirm each other as to the general characteristics of such systems, and their differences will identify those parts of his experience that are particular and not generalizable.
</p>

<p>
This effect can manifest itself in a few ways.  First, we tend to see the rewrite  as an opportunity to eliminate all the technical debt we accrued in the past system.  We want to decompose God classes, fix inconsistent variable naming, re-shuffle and restructure data structures, and so on.   Basically, we see this as our chance to resolve all of our little peccadillos with the legacy code, because it wouldn't feel right to port that debt into the new codebase.  
</p>

<p>
Additionally, it's also easy to think of the rewrite as not just a chance to modernize certain pieces of the architecture that are flawed, deficient, or out of support, but also as a <b>vehicle to leap-frog everything to the cutting edge</b>.  Maybe the UI is still the old AngularJS and doesn't render well for mobile web users, so it does seem justified to port to a more modern web framework. But while we're at it, let's also break the backend up into microservices and write them in Go!  Essentially, the rewrite can become like a piece of legislation - it may start out as a simple bill to reduce gun violence, but by the time it gets passed into law West Virginia is getting five new bridges and Oregon's farmers are being subsidized to grow soy.  
</p>

<p>
And the Second System Effect is not just specific to developers.  Oftentimes business stakeholders will take the same tact, but with <i>their</i> priorities.  "We might as well add this feature to the rewrite that the customers have been dying for, since we'll be touching that code anyway."  And just as with the technical improvements and embellishments, the scope just gets bigger and bigger and the release date of the rewrite gets pushed back further and further.  In the end, while the mantra of development for the initial system was "get something up and running fast!", for the rewrite it can be "we'll never get another chance to do X, Y, and Z!" 
</p>

<h2>Fighting the Last War</h2>

<p>
It's often said that generals in peace time prepare themselves to fight the last war.  They look back and reflect on the flaws and faults of their old battle plans, and vow to never let those mistakes happen again.  And then the next war comes, and it's nothing like the last.  Their preparation was for naught.  The same can happen with a rewrite.  We are so keenly aware of our mis-steps of the first system, that when it's time to design the second, we make sure above all else that we don't get burned again in the same way.  But it's easy to miss that things have changed.  Those past mistakes may be non-issues at the point we rewrite, and so it's not necessary to go to any ends to prevent them.  At the same time the modern technologies being used in the rewrite  have introduced a whole new set of issues that we haven't yet looked ahead to spot.  
</p>
<img class="content-image" src="http://www.bennorthrop.com/rewrite-or-refactor-book/last-war.jpg" width="200" />

<p>
In my early years of consulting, I helped build for a client a large web-app that served a few thousand internal users.  The application was a success - meaning that we delivered the functionality within time and budget (plus or minus), but we unknowingly hitched our "horse" to the wrong wagon, so to speak.  These were the early days of single-page apps, so we used a budding framework called Google Web Toolkit, which was quite cool at the time (you'll have to take my word on this).  Unfortunately, a year or so after this app was launched, Google effectively jumped ship from GWT in favor of something better (Angular), leaving everyone (including this client) stranded on an essentially unsupported technology.  Not a good situation, though in our defense it would have been difficult to predict.
</p>

<p>
Years later, I had the chance to reconnect with some of the developers still there, and they told me they had no choice but to rewrite the app.  And rightly so.  But when I asked what tech stack they had picked, I was surprised.  Not wanting to be burned by single-page app technology or a flash-in-the-pan framework, they chose an incredibly mature but decade-old server-side page rendering technology, despite the fact that single-page frameworks were, at that point, extremely solid and used by, well, everyone, and their app had some very rich user interaction that could have benefitted from that model.  In other words, the central driver for their rewrite was to avoid the mistakes of the first system, but in the process they missed out on many of the advantages of modern web frameworks.  They were fighting the last war.
</p>

<h2>All or Nothing</h2>
<p>
The last big hazard of a rewrite is something that can be avoided (as we'll discuss in later chapters), but often is not.  While we now accept the wisdom of iterative development and the concept of the <a href="https://www.agilealliance.org/glossary/mvp/">Minimum Viable Product</a>, with a rewrite it can be difficult to find a way around delivering <i>everything</i> all at once in one big bang.  For example, if the customers have been using the legacy system which has, say, one hundred features, how can we deliver a new system with anything less than those one hundred features if we expect them to (happily) switch over?  Basically, the rewrite needs to do everything the old system did, and so it would seem that we must first deploy the entire replacement before we can get back to iterative development.  Depending on how big the existing system is though, this can represent a considerable effort.  
</p>

<p>
Further, this "all or nothing" requirement can combine with the ever constant demands of the business to put incredible pressure on the team.  If the team can't deliver <i>anything</i> until it's all finished, then they aren't able to show any tangible value until the replacement is launched.  The business is in a sense being held captive by the rewrite effort, and it's up to them to stay patient and trust in their development team to finish. Not an easy feat.  If the customers are especially demanding or if the team consistently hits unexpected delays and issues (e.g. "unknown unknowns", etc.) that push the release date out for the rewrite, the business might feel like it has to apply pressure (which can force the team to cut corners) or can pull the plug altogether.  
</p>

<h2>Summing Up</h2>
<p>
In the end, hopefully some of the dangers that lurk in the Rewrite phase are now more visible.  While the greenfield stage of development surely has its perils, the rewrite is no walk in the park either.  The challenges of parallel development, team organization, feature and technology gold plating, and big-bang deployment can easily drag down the most competent of teams.  And so it would seem that we would be apprehensive about taking on a massive rewrite.  As we'll see in the <a href="http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-3-why-we-rewrite-even-when-we-shouldnt.php">next chapter</a>, surprisingly, this isn't always the case.  Despite the mortal dangers to teams in the rewrite phase, we often put caution to the wind and take the journey of a rewrite anyway.
</p>
				]]>			</description>
			<pubDate>Tue, 14 Jul 2020 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-2-the-risks-of-rewrites.php</guid>
		</item>
		<item>
			<title>Why we Rewrite (Even When we Shouldn't)</title>
			<link>http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-3-why-we-rewrite-even-when-we-shouldnt.php</link>
			<description>
				<![CDATA[				<section id="setup-blurb">
Note: I've been thinking about writing a book on the topic of <a href="http://www.bennorthrop.com/rewrite-or-refactor-book/index.php">rewrite or refactor</a> for years now.  Over the winter I finally "broke ground" on the project, and started with this chapter.  My plan is to release the rest of the book piecemeal and publish when it's done.  Feedback welcome!
</section>

<p>
As we saw in the <a href="http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-2-the-risks-of-rewrites.php">previous chapter</a>, a software rewrite can be a dangerous undertaking - there are a number of very real costs and risks that can sink even the most well-intentioned effort.  And yet we do rewrite!  Often.  Despite the warnings and obvious dangers, we come together, business and technology, and collectively declare: "damn the torpedoes, we're rewriting this old pile of code, and this time we'll succeed!"  
</p>

<img class="content-image" src="http://www.bennorthrop.com/rewrite-or-refactor-book/skyscraper.jpg" width="250" />


<p>
The question I'd like to explore in this chapter is "why".  Given all the costs and risks, why do we so often choose to rewrite a working legacy system rather than refactor it in place?  Leaning on insights from psychology, sociology, and other fields, I'd like to expose some subtle and not-so subtle forces that serve to <b>nudge each of us toward the path of the full-scale rewrite</b>.  Though none of these individually are the ultimate reason we choose "big modernization", together I think they form a powerful undercurrent that float us in that direction.  
</p>

<p>
I want to be clear though.  I'm absolutely not arguing that a rewrite is always the wrong choice - there are many good and justified reasons to rewrite, which we'll see in the <a href="http://www.bennorthrop.com/rewrite-or-refactor-book/">next chapter</a>.  And further I'm not trying to cast aspersions on developers or other stakeholders for making "bad" decisions.  We do all have blind spots and biases, however. When we're aware of them, we can work to counteract them - which in this case might mean sparing ourselves and our organizations from sinking countless hours and dollars into what might be a doomed rewrite.  With those caveats out of the way, let's take a look at some of these forces at play...
</p>

<h2>The Enjoyment of Creation</h2>
<p>
Developers enjoy the act of creation.  We are builders by nature.  Though we understand that the job often requires us to bravely venture into the dark recesses of others' code to slay some lurking defect or tweak some abstruse calculation, this isn't what attracts us to programming.  It's just a necessary evil.  When given the chance, we want to build our own systems.  We want to craft a solution to a problem in the way that makes sense to us, in the style that appeals to us.  At the risk of sentimentalizing, programming is our art.  In the same way a painter would prefer to start from a clean canvas than paint within the portrait of another, all things being equal, we too want to give life to our own creation.    
</p>

<p>
In fact, there is evidence that this fondness we have for the things we've made ourselves is not just a part of the psyche of programmers but is built into all of us.  Dan Ariely, in his book <a href="https://www.amazon.com/Payoff-Hidden-Logic-Shapes-Motivations/dp/1501120042">Payoff: The Hidden Logic That Shapes Our Motivations</a>, gives an interesting anecdote that underscores this human tendency:
</p>

<p class="indentableSubtle">
Consider cake mixes. Back in the 1940s, when most women worked at home, a company called P. Duff and Sons introduced boxed cake mixes. Housewives had only to add water, stir up the batter in a bowl, pour it into a cake pan, bake it for half an hour, and voila ! They had a tasty dessert. But surprisingly, these mixes didn't sell well. The reason had nothing to do with the taste. It had to do with the complexity of the process but not in the way we usually think about complexity.<br/><br/>

Duff discovered that the housewives felt these cakes did not feel like the housewives' own creations; there was simply too little effort involved to confer a sense of creation and meaningful ownership. So the company took the eggs and milk powder out of the mix. This time, when the housewives added fresh eggs, oil, and real milk, they felt like they'd participated in the making and were much happier with the end product.

</p>

<p>
Ariely goes on to describe a number of scientific studies that show this exact same effect: we are in fact hard-wired to enjoy creating things, and further when we do create, we overly value that which we've built to the creations of others (independent of how good what we've produced actually is!).  
</p>

<p>
I think this directly speaks to how we as developers can feel about maintaining legacy systems.  Sure, we're capable of rotely following some prescribed pattern to add a new column to the report or button to the screen, but that doesn't give us that feeling of attachment or meaning to our work.  What we'd like is to crack our own eggs and mix in our own milk and oil.  In other words, our brains may naturally tend toward wanting to rewrite over refactor.
</p>

<h2>The Drudgery of Maintenance</h2>
<p>
The flip side of seeking out enjoyment from the act of creation is avoiding frustration from the drudgery of maintenance.  And there is plenty of frustration built into legacy systems.  Over time, software <a href="http://www.laputan.org/mud/">tends toward decay</a>.  Business requirements shift, forcing developers to remodel what used to be the kitchen into the front porch.  Critical deadlines force us to cut corners, and ship code with TODOs and copy-and-paste.  And the comings-and-goings of old and new developers to the system create what, over time, look like sedimentary layers in the architecture - "you can see from the style that this code comes from the pre-IPO period, before the time of dependency injection".
</p>

<img class="content-image" src="http://www.bennorthrop.com/rewrite-or-refactor-book/big-ball-of-mud.jpeg" width="200" />

<p>
Working within legacy code like this can be frustrating to say the least.  To fix even the simplest bug might require us to trace through convoluted execution paths as they wind in and out of different software ghettos, where weeds have grown tall and broken windows have gone un-fixed.  Keeping the logic (or illogic!) of the system in our heads can be a herculean task.  And while we dutifully accept our fate and fix those defects and add those small enhancements, all the while we think about how we wish we could do it differently.  We dream about how cathartic it would be to put a torch to this bastion of complexity and technical debt and start over from scratch.  
</p>

<p>
To the end user and perhaps even to the business, however, it may be a different story.  Sure the legacy system might not be as visually pleasing or it might require a few more clicks or seconds than might be preferred, but it likely still works.  The system is functional, relatively reliable, and the business processes around it, though not optimal, are at least well understood.   But to the developer, especially one who was not the original creator (see above!), the system can represent not comfort but frustration and constraint.  And the more time we work within it, the more we want to escape and rewrite it.
</p>

<h2>Self-Interest and Fashion</h2>
<p>
Beyond just seeking enjoyment or avoiding frustration, we as developers are also well aware of what tangibly benefits us and our careers, and often it's not maintaining legacy systems.  A <a href="https://insights.stackoverflow.com/survey/2019">2019 Stack Overflow developer survey</a> shows a direct correlation between the newness of a language and the amount of money a developer makes.  Whereas the average age of top 5 languages by salary is just 15 years old, the average age of the bottom 5 languages is 39 years old.
</p>  

<table width="300" align="center" border="1" class="simpleTable" cellpadding="2">
<tr>
  <th>Language</th>	
  <th>Age</th>
  <th>Avg Salary</th>
</tr>
<tr>
  <td>Clojure</td>
  <td>13</td>
  <td>$90k</td>
</tr>
<tr>
  <td>F#</td>
  <td>15</td>
  <td>$80k</td>
</tr>
<tr>
  <td>Go</td>
  <td>8</td>
  <td>$78k</td>
</tr>
<tr>
  <td>Scala</td>
  <td>17</td>
  <td>$78k</td>
</tr>
<tr>
  <td>Elixir</td>
  <td>9</td>
  <td>$76k</td>
</tr>
</table>
<p style="width: 100%" align="center">
<i>Top 5 Languages by Average Salary</i>
</p>

<table width="300" align="center" border="1" class="simpleTable">
<tr>
  <th>Language</th>	
  <th>Age</th>
  <th>Avg Salary</th>
</tr>
<tr>
  <td>HTML/CSS</td>
  <td>25</td>
  <td>$55k</td>
</tr>
<tr>
  <td>VBA</td>
  <td>27</td>
  <td>$55k</td>
</tr>
<tr>
  <td>Assembly</td>
  <td>71</td>
  <td>$52k</td>
</tr>
<tr>
  <td>C</td>
  <td>48</td>
  <td>$52k</td>
</tr>
<tr>
  <td>Java</td>
  <td>25</td>
  <td>$52k</td>
</tr>
</table>

<p style="width: 100%" align="center">
<i>Bottom 5 Languages by Average Salary</i>
</p>

<p>
Now of course many other factors play into these numbers, but all things being equal, it's pretty clear that if we don't keep pace with newer technologies, the amount of money we can expect to make will be less.  This is probably not surprising for any developer who has recently been on the job market.  Recruiters, resume bots, and even fellow developers are hunting through our experiences for the latest buzz words: microservices, Kubernetes, progressive web apps, or whatever is the technology du jour.  The newer and more cutting edge, the better.  The logic, presumably, is that a developer who is up on the latest skills must be more motivated and invested in their craft than someone who has only been doing the yeoman's work of maintaining a legacy system, (the irony being that working within the legacy system might have been the right thing from the perspective of the prior employer!).
</p>
 
<p>
Now some of this does make sense.  The job of programming does entail a high degree of exploration and experimentation, and so a passion for learning is indeed important.  However, there's a tendency, I think, for our industry to sometimes favor fashion over substance.  When we pick a language, tool, or framework, of course we want to choose the one that is right for the job, but we also consider what the choice says about us.  Are we the kind of person that uses a proven but stodgy language like Java, or are we "forward-thinking" and "innovative" and pick Go or Kotlin?  In a sense, the technologies we use are like the clothes we wear - they speak to who we are, what we stand for, our worth. It can be <a href="http://www.bennorthrop.com/Essays/2015/slaves-to-fashion.php">technology as fashion</a>.
</p>

<p>
Now of course the analogy is far from perfect, but consider some parallels from this description of the <a href="http://onlinelibrary.wiley.com/doi/10.1111/j.1533-8525.1969.tb01292.x/pdf">fashion cycle</a> by sociologist <a href="http://en.wikipedia.org/wiki/Herbert_Blumer">Herbert Blumer</a>:
</p>

<p class="indentableSubtle">
The elite class seeks to set itself apart by observable marks or insignia, such as distinctive forms of dress. However, members of the immediately subjacent classes adopt these insignia as a means of satisfying their striving to identify with a superior status. They, in turn, are copied by members of classes beneath them. 
<br/>
<br/>
In this way, the distinguishing insignia of the elite class filter down through the class pyramid. In this process, however, the elite class loses these marks of separate identity. It is led, accordingly, to devise new distinguishing insignia which, again, are copied by the classes below, thus repeating the cycle.
</p>

<p>
In a nutshell, fashion, whether in clothing, music, or programming, is about class differentiation. The elites innovate. The masses catch up so they can be associated with the elites. As soon as they do, however, the elites are no longer "elite", and so they must break away and innovate again. The masses eventually follow, and the cycle continues, ad inifinitum.
</p>

<p>
When it comes to the question of rewriting or refactoring, I think this can be another subtle force that pushes us as developers toward the choice of full-on modernization.  To keep an existing system alive is akin to wearing your clothes from a decade ago.  Sure, they may still keep you warm and dry, but they are old and worn and probably don't present to the world the image you want show.  And for those who aren't prone to the frivolousness of fashion, we have to at least know that it does tangibly affect our careers.  Keep pace or make less.  
</p>

<h2>Faulty Intuition and Mental Short-cuts</h2>
<p>
Putting motivations and self-interest aside, there is another powerful force which can compel us to believe that rewriting is the obvious and best decision for our legacy systems even when it's not: our own intuition.  In his amazing book on decision making and cognitive bias, <a href="https://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman-ebook/dp/B00555X8OA">Thinking Fast and Slow</a>, Daniel Kahneman explains that while it's easy for us to form opinions on all types of questions (and to be confident in these opinions to boot!) oftentimes they're based on simple mental short-cuts, and not solid reasoning.  For decisions where the stakes are small this might be ok, but for the question of whether to refactor or rewrite an entire system, where hundreds if not thousands of hours of effort could be at stake, this isn't going to cut it.  We need to be sure.  
</p>

<p>
One of these subtle mental short-cuts we use is called <a href="https://thinkproductive.co.uk/decision-thinking-substitution-bias/">substitution</a>.  When confronted with a question that would require deep effort and analysis (which is hard work!), we often just swap in an easier proxy question that we can answer more quickly.  For example, to know whether it's worth it to rewrite vs. refactor, we <i>should</i> understand what the cost of a rewrite would be, how much value it would bring to the organization, when ROI would be realized, and so on.  But this is hard!  So instead, we substitute in questions that are easier to answer like  "is the existing system buggy?" or "is the UI out-of-date?".  You bet it is!  And while it seems like we addressed the original (hard) question, we actually didn't - we just swapped it for something simpler.  
</p>

<p>
Over the years, I've seen this type of justification over and over.  Rather than pause to try to answer the real but difficult question - whether the net value of a rewrite is greater than the net value of a refactor - we often  fall back to easier substitute questions.  We say things like "we're going to rewrite because the legacy system is hard to work with" or "because no one understands it".  Yes, <b>these answers are relevant, but they're just not sufficient</b>.  Maybe it's true that no one understands the code, but how much would it cost for a person to gain that understanding?  And is that cost greater than or less than rewriting the entire system from scratch (which would probably require understanding it all anyway!).  Ditto for bugs or tech debt.  What are the costs and returns?
</p>
 
<p>Now of course we live in a world that moves fast - we don't have infinite time to analyze, make business cases, and pontificate.  But for a question as crucial as rewrite or refactor, we should try to slow down a little and make sure we're at least answering the real question, and not an easier substitute one.
</p>



<h2>Throw-Away Culture</h2>
<p>
This last force that can push us toward a rewrite is not rooted within us, but rather in the society around us.  We live in a <a href="https://en.wikipedia.org/wiki/Throw-away_society">throw-away culture</a>.  Our food and beverages come in one-time use containers.  The products we buy are garbed in excessive plastic and paper packaging.  And our appliances and devices are <a href="https://en.wikipedia.org/wiki/Planned_obsolescence">designed for obsolescence</a>, so they can't be repaired even if we wanted to.  In other words, we've been conditioned to throw things away without a second thought - whether its dented, cracked, malfunctioning, or just slightly old or worn, we toss it out.  
</p>

<p>
And so, I think it's at least possible that this same <b>"throw-away first" attitude affects the way we think about our software</b> as well.  When a system ages, our inclination is not to pull out the duct tape and WD40 to give it a few more years of life, it's to throw it to the curb and go out and get (or in this case build!) the newer model.  In fact, it seems that the very word "legacy" can induce groans of sympathy from our colleagues.  "I'm sorry you have to work on that", they say, "when are you going to rewrite?"
</p>

<img class="content-image" src="http://www.bennorthrop.com/rewrite-or-refactor-book/pc-dump.jpg" width="250" />
<p>
Now to be fair, our industry is one of constant improvement and innovation.  We are continually learning better and cleaner ways of doing things and then incorporating them into our tools, frameworks, and languages.  No one would ever purposely use Java 7 when they could use streams and lambdas from Java 8, or even a more concise or functional language like Kotlin or Scala.  Additionally, new platforms and devices are constantly being released, which our existing systems may not port to.  So I'm not saying that scrapping the old for the new is necessarily a frivolous choice, as we'll see in the next chapter.
</p>

<p>
I do think it's helpful though, like with the other forces, to be aware of this potential bias.  In the same way that there are very real costs to our society for our thoughtless waste, there can be costs to the organization when we too quickly abandon a legacy system that may be reliable, albeit a little old or complex.  In the following chapters, I'd like to argue for a different three "R"s of legacy modernization: "repair", "reuse", and "recycle".  Instead of seeing our existing systems as things we need to distance ourselves from, I think we should appreciate and leverage the components and elements that <i>are</i> working, and only seek to rewrite that which we need to.  
</p>

<h3>Wrapping Up</h3>
<p>
At this point, we've seen the many dangers and risks that await us on our journey to rewrite, and we've seen the subtle forces that nudge us in that direction despite it all.   In the next chapter we'll look at when a full-scale rewrite does make sense - the reasons, constraints, and drivers that justifiably push us to abandon our existing systems and start afresh.  If done for the right reasons, a rewrite can be a real opportunity to improve things we care about - user experience, maintainability, performance, and the ability to add new features and address new use cases.
</p>
				]]>			</description>
			<pubDate>Tue, 19 May 2020 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/rewrite-or-refactor-book/chapter-3-why-we-rewrite-even-when-we-shouldnt.php</guid>
		</item>
		<item>
			<title>The Myth of Architect as Chess Master</title>
			<link>http://www.bennorthrop.com/Essays/2020/myth-of-software-architect-as-chess-master.php</link>
			<description>
				<![CDATA[				<p>
For software architects (especially at <a href="http://www.bennorthrop.com/Essays/2019/programming-at-a-big-company.php">bigger organizations</a>), it's not that uncommon to get a request like this from a manager or director:
</p>

<p class="indentableSubtle">There's this tough problem the developers have been struggling with for weeks (performance, or scalability, or whatever), so can you quickly look at it and show them the best practice, quick fix, etc. that solves it all?
</p>

<p>Reasonable ask?  No, not really.  The expectation is that <b>the architect is a chess master</b>.  It's just like that movie we've all seen.  There's the young or disheveled or [insert surprising adjective] savant who, walking through central park mid-dialogue with someone else, glances for a nano-second at a pair playing chess and declares "bishop to queen 4, check mate" and then keeps walking.  Minds blown.</p>

<img src="http://www.bennorthrop.com/Essays/2020/chess-master.jpg" align="right" width="250" />

<p>
But why shouldn't an architect be able to size things up as quickly as a chess master?  Both an architect and a chess master have accumulated thousands of hours of experience in their disciplines.  Both are analyzing current states of a "board" and then evaluating the trade-offs of different next moves or options.  
</p>

<p>
The difference is that chess masters are always playing the <i>exact same game</i>.  Rooks always go forward-backward and side-to-side.  Bishops always move on diagonals.  And because the rules don't ever change, it's easier to take a mental snapshot of a board and instantly pattern match back to some other past experience - e.g. "this is exactly like the game I played/studied four months ago". 
</p>

<p>
Any given software system, on the other hand, may look the same as countless others you've worked on in the past - I mean, hey, it's all ifs and elses, classes and objects, REST and SOAP calls, etc. - but just a little bit below the surface we realize the pieces and the rules are very different.  In my system the rook can jump the first 2 squares but in yours  the queen has 3 lives.  Each system we visit has different intricacies and rules we must learn anew.    
</p>

<p>
This immense variability and complexity is baked into even the simplest software system - it's in the business domain, in the frameworks/techologies used, and in the implementation itself - and so it takes time to grok all these nuances and details before we can build the right mental picture that allows us to reason about it effectively.  Even for those with years of experience this is true.  Sure there are common patterns, styles, tools, specifications, etc. that, if you know them, can help in terms of more quickly sizing up a system, but almost never do these alone allow you to pull off that type of chess savant "mate in one" mastery.  Real-world software solutions take time.  Architecture takes time.
</p>

<p>
This is why I think it's important to think about <b>software architecture as a process and not a destination</b>.  Being an architect (or playing the role of an architect) doesn't mean simply <i>divining</i> the "right" solution or recommendation and handing it off to the developers.  Anyone can whip up a bunch of boxes and lines that <i>seem</i> plausible, but do they really apply to the game of "chess" you're playing now, or the one from your past project or from that popular blog post?  To truly know the right next "move" requires first understanding the rules of the game you're in.  What are the business drivers, risks, technical constraints, legacy components, integrations, possible options, trade-offs, and so on.  These are the details that take time to identify, clarify, and understand, and they are subtly (and sometimes not so subtly) different from project to project and organization to organization.   
</p>

<p>
In my opinion, the expectation for the architect should be to setup the framework or process by which good architectural "moves" are made (Michael Keeling describes this well in <a href="https://www.amazon.com/Design-Programmer-Architect-Pragmatic-Programmers/dp/1680502093">Design It</a>).  Thinking an architect is going to stroll into a meeting and find a check mate lurking in plain site is sadly unrealistic.
</p>
				]]>			</description>
			<pubDate>Mon, 06 Jan 2020 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2020/myth-of-software-architect-as-chess-master.php</guid>
		</item>
		<item>
			<title>Programming at a Big Company</title>
			<link>http://www.bennorthrop.com/Essays/2019/programming-at-a-big-company.php</link>
			<description>
				<![CDATA[				<section id="setup-blurb">
A few years back while working as a programmer at a big company I wrote this random story after an excruciatingly frustrating conference call. I thought better about posting it then, but the other day I stumbled across it and figured why not...maybe it'll resonate for someone out there..
</section>

<p>
You're an avid marathon runner, and are pretty fast to boot.  It's your first race as part of a new running club, and you're excited.  The club is big and, some say, impersonal, but you were lured by its longevity and reputation...and of course the kick-ass benefits - massages, gear, the works.  
</p>

<p>
Anyway, it's the morning of the race, and you show up at the course.  You head over to the club's meeting spot, and the first person who spots you is the health specialist.  "Nice that they care so much about my health to have a dedicated specialist", you think.
</p>

<p>
After a friendly introduction, the health specialist says, "We need you to wear this backpack while you run, for your safety".
</p>

<p>
 "Seriously?" you ask.  "Won't it slow me down?"
</p>

<p>
"Well, it might, but it's really important because it has all types of essentials in it: bandaids, wraps, braces, ice packs, and a book of medical conditions.  All our runners wear them, so it shouldn't be a big deal."
</p>

 <p>
"Ok", you say reluctantly, "if you say so", and you strap on your backpack.  The thing must way 15 pounds.  
</p>

<p>
At that moment, the club's race coordinator ambles over.  "Hey-o", he greets you warmly.  "It's really important to know where all our runners are during the race, so we'd like you to strap on this ankle bracelet tracking device".
</p>

<p>
Again, you push back a little, "Won't this rub on my ankle and give me a blister?  And can't I just use my phone?"
</p>

<p>
"Nope, I'm sorry", he says, "club policy."
</p>

<p>
As you finish attaching the bracelet to your ankle, you look up, and are met by the club's gear specialist.  She hands you a new pair of shoes.  "We like that all our runners wear the same shoes, just for consistency."
</p>

<p>
"But, this isn't the brand I usually wear", you stammer, "and wait...these are size 12, and I wear a 10".  
</p>

<p>
"Yes, we know.  We like everyone to wear the exact same pair of shoes, so that we all are wearing the same pair of shoes."
</p>

<p>
"That doesn't make sense, though.  I have a different foot type than the other runners", you plead.  But it's no use.  You put on the shoes.
</p>

<p>
Finally, you make your way over to the starting line, but right before you get there you bump into the club's running strategist.  He hands you a shiny, color pamphlet with a bunch of nice info-graphics in it.  "Please read this before you run.  It explains our micro-burst strategy for racing", he says.  "Basically, we'd like you to sprint for 30 seconds, then walk for 30 seconds, then sprint again, then walk, and so on."
</p>

<p>
"Wait, what?", you question.  "Does that work?  Do I do that for 26 miles?  And have you actually tried this before?  Are you even a runner?"
</p>

<p>
"No...well...I used to run 15 years back, but I don't do that anymore.  Running is kind of, you know...low-level.  I do read a lot about running though, and now I just help runners by telling them about best practices.  Anyway, you better get to the race, it's starting in a minute."
</p>

<p>
"Ok, whatever."  You're beginning to feel a little jaded by all of this encroachment, and you just want to get to doing the thing you enjoy: run.
</p>

<p> 
With just a few seconds before the gun goes off, you see the head coach out of the corner of your eye.  He screams out, "we need you to run this race in under 2 hours.  Can you commit to that?"
</p>

<p>
"Are you crazy?", you shout back.  "Even without all this crap, the fastest I could possibly run it in is a 3:30".
</p>

<p>
"I'm sorry, but I need you to commit to running under 2 hours.  Can you do it?"
</p>

<p>
"Are you asking me?"
</p>

</p>
"No, not really.  So can you do it?", he again prods.
</p>

<p>
"Ummm...sure, whatever.  I'll run it in 1:59." you shout back.
</p>

<p>
"Great.  I'll mark you down for 1:40, because it shouldn't be that tough.  Just push hard.  You can do it."
</p>

<p>
The gun goes off, and right from the start, you feel weighed down by the backpack and you're tripping over your shoes every 5th step.  You try a few micro-bursts, but obviously that doesn't work.  No fucking surprise.  You're getting bitter.  
</p>

<p>
A few racers pass you, and then a few more.  Some of the other racers are running solo, but some are racing for other, smaller clubs.  Everyone seems so much freer.  And faster.
</p>

<p>
You slog through.  By mile 15 the ankle brace has rubbed through the skin.  Your shoulders are in knots from the backpack.  You look over and see the coach behind a barrier, staring at you and gesturing to his watch impatiently, the international sign for "hurry up".   
</p>

<p>
You push harder, surrounded now only by people from your club.  Everyone else has passed you by.  You pound through the remaining miles, and get to the finish.  The clock says 5 hours and 47 minutes, but it feels like longer.  
</p>

<p>
Despite all the pain, you do feel a strange sense of satisfaction.  Sure, you're 2 hours over your usual marathon time, but the fact that you finished it at all is an accomplishment.  You high-five the handful of runners from your club who were able to finish, then go get your massage, put your new gear in your backpack, and walk to your car, vowing never to run for a big club again.  
</p>

<p>
...
</p>
<h3>
Afterward
</h3>
<p>
I've done a few stints at large companies, and actually have appreciated and learned from each opportunity - but it was certainly frustrating.  For those fighting the good fight at these companies, I have great respect.  In my experience, the toughest problems to solve in these environments are often not the technical ones, but the social, political, and organizational ones, and with a little mindset adjustment, I think they can be just as interesting and challenging, but it's obviously hard when what you probably most want to do is just build good software.  
</p>
<p>
In the way of advice (because what kind of blog post would this be without advice?), here are a few survival tips I picked up during my tours of duty in corporate-land.  First, <b>be a little bit cunning</b>.  Just a little bit though.  Not deceitful or malicious, and not to pursue your own ambition, but make the conscious decision that your job is to do what's best for the company, and sometimes this means finding ways around or through the over-bearing policies that get in the way of that.  "Forgiveness over permission" seemed to be the mantra of the most effective programmers I met.
</p>

<p>
Second, <b>use your work</b> to get past the blocks and blockers.  If an ivory tower architect tells you that your approach is impossible or sub-optimal, go back to your computer, put in the extra hours, and at your next chance give a demo of how it <i>does</i> work.  Or better yet, show your prototype <i>before</i> you get any feedback.   In other words, put in the work, and then let it speak for you - try not to get bogged down in the endless meetings and other bureaucratic shenanigans.  
</p>
<p>
Anyway, I'd love to hear any of your tips or tricks for not just surviving but thriving (and dare I say, enjoying) life as a programmer at a big company.  Please share!
</p>
				]]>			</description>
			<pubDate>Mon, 14 Oct 2019 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2019/programming-at-a-big-company.php</guid>
		</item>
		<item>
			<title>REST API Versioning with API-first and OpenAPI (Swagger)</title>
			<link>http://www.bennorthrop.com/Essays/2019/api-versioning-with-openapi-and-api-first.php</link>
			<description>
				<![CDATA[				<p>
There are already a lot of <a href="https://blog.apisyouwonthate.com/api-versioning-has-no-right-way-f3c75457c0b7">great</a> <a href="https://blog.restcase.com/restful-api-versioning-insights/">resources</a> out there on the whys, whens, and hows of REST API versioning, and we seem to be settling (more or less) on some general <a href="https://nordicapis.com/introduction-to-api-versioning-best-practices/">best practices</a>.  Likewise, there abounds a ton of info on the advantages, strategies, etc. for taking an <a href="https://swagger.io/resources/articles/adopting-an-api-first-approach/">API-first</a> approach with <a href="https://swagger.io/docs/specification/about/">OpenAPI</a> (formerly <a href="https://swagger.io/">Swagger</a>).  
</p>

<p>
Surprisingly, however, there's not a lot out there on the intersection of the two - i.e. what's the best way to version REST APIs when doing API-First with OpenAPI?  I'm just getting familiar with OpenAPI, but in this post I hope to take a stab at this question.
</p>

<h3>Do you really need to version?</h3>
<p>
Probably the best place to start first is to make sure versioning is actually needed for a particular service.  Independent of OpenAPI, a good versioning solution takes a <a href="https://stackoverflow.com/questions/389169/best-practices-for-api-versioning">non-trivial amount of forethought</a> and development effort, and if you can avoid having to version altogether you can save a lot time and energy.  Versioning an API is only necessary when either:

<ol>
<li>You don't own the clients calling your API (e.g. you're providing an API to others)<br/>
<br/></li>

<li>You do "own" the clients, but for whatever reason (there are too many, etc.) you aren't able to coordinate updates of the service/API with updates of the clients</li>
</ol>

<p>
Basically, if you're building a publicly available API, then versioning is of course necessary.  Or even if you have some internally available microservice but it's called by many other clients (microservices, UIs, etc.) from other departments on different release schedules, etc., then versioning might also be crucial since it would be tough to force the clients to update in step with the service.  
</p>

<p>
If what you have, however, is a service that has just a handful of other clients, all of which are owned by your development group and could conceivably all be upgraded/released in step, then it might be better to <b>skirt the versioning issue altogether</b> and just a support a single, canonical but <a href="https://www.radcortez.com/rest-api-evolution/">evolving API</a>.  In other words, when the API changes, either do it in a way that doesn't break existing clients, or if a <a href="https://www.bennadel.com/blog/3501-when-is-a-change-a-breaking-change-for-an-api.htm">breaking change</a> <i>is</i> necessary then go and update all the clients as well to adjust to the API changes, and release them altogether.  Sure there are short-term coordination and development costs to doing this, but they may be less than the long-term costs that come with creating and sustaining a versioning strategy and all that comes with that (backward compatibility, deprecation, etc.).  
</p>

<p>
TLDR; versioning is hard, and if you don't have to do it, don't!
</p>

<h3>When you do need to version</h3> 
<p>
Ok, with all that out of the way, if it <i>is</i> determined that you need versioning, then how do you do it using OpenAPI and API-first?  The central concept in API-first is obviously is the API spec itself, from which everything else is generated (clients, server stubs, documentation), so the big question is what to do with this?  Specifically, how many API specs should there be (e.g. one per version, etc.)?  And what do they encompass?  It seems to me like there are two main options: (1) put all versions in one API spec, or (2) create a new API spec per version.

<p>
The first option, <b>putting all versions of an API into a single api spec</b>, does seem to have a few advantages.  First, everything is in one yml file (i.e. paths for all versions of resources) and from this single spec, everything can be generated (e.g. clients, server stubs, etc.).  Clients, services, stakeholders, etc. just need to look to one artifact for what they need, regardless of what versioning they're using.
</p>

<img src="/Essays/2019/open-api-and-versioning-all-in-on3.png" class="center" />

<p>
Additionally, this allows for easily versioning at a resource-level, and not an API-level.  For example, say there are just three resources:
</p>

<p class="indentable">
<pre>
/resourceA
/resourceB
/resourceC
</pre>
</p>

<p>...and say only one of the three changes, resourceA.  With a single API-spec it's possible to only version the one that changed, resourceA, such that it would have both a /v1 and /v2, but the other resources, resourceB and resourceC, just have a /v1.  
</p>

<p>
There are a couple major downsides though.  First, having all the different versions in one spec will eventually get muddled in that even though it's easy to create new paths for each version of a resource, it's likely different versions of the components (data classes) will need to be created too, which are very similar to each other (e.g. Resource1V1, Resource1V2, etc.).  A little messy.  Additionally, if you're using the spec to generate clients, then clients could wind up with <i>all</i> versions of paths to choose from (unless tagging or whatever is used to generate a client with only v1).  <a href="https://idratherbewriting.com/learnapidoc/pubapis_openapi_step7_tags_object.html">Tagging</a> can be helpful here to only generate some portion of the API spec for a given client, but this could be tricky.
</p> Lastly, the generated classes (server stubs, component objects, etc.) for all the versions would end up in the same package, resulting in a bunch of classes like Resource1V1Controller and Resource1V2Controller, etc.  Very messy.  

<p>
The alternative is to <b>create a new API spec for each version</b>, and within this there are two sub-options: version at a resource-level or version at an API-level</p>

<img class="center" src="/Essays/2019/open-api-and-versioning-spec-per-version.png" />

</p>
Versioning at a resource level is possible, such that if resourceA changed from v1 to v2, but resourceB and resourceC stayed the same, then only resourceA could be moved to the api-v2.yml.  This makes it clear what changed, but without some generation gymnastics, might require a client to import/bring in both clients for both v1 and v2.
</p>

<p>
The alternative here is enforce that the API is versioned altogether.  From the perspective of the organization of the API spec, this seems much cleaner, but there will probably be a lot of redundancy across versions.  For example, again if only resourceA changed from v1 to v2, and resourceB and resourceC stayed the same, you'd have to copy-paste over the entire specification for resourceB and resourceC into the v2 spec document even though they didn't change.  This duplication just feels wrong, but if you don't like the other options, it might be a necessary evil though.  
</p>

<p>
It's probably important to mention here that there is a version property in the API spec itself, and while it would seem that this should define the version of the API itself, it actually is intended to define the version of the API specification document (a subtle nuance that was a little confusing to me).  
</p>

<p>
There's plenty more to discuss, but I just wanted to broadly paint the different options.  The take-away for me is that versioning is not easy, and when you can, it's better to evolve an API either in a way that is non-breaking for clients or to evolve the API and clients at the same time.  Creating an entire new version of an API should only as a last resort.  I'd love to hear anyone else's thoughts! 
</p>
				]]>			</description>
			<pubDate>Thu, 18 Jul 2019 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2019/api-versioning-with-openapi-and-api-first.php</guid>
		</item>
		<item>
			<title>The Trouble with Tech Debt</title>
			<link>http://www.bennorthrop.com/Essays/2019/the-trouble-with-tech-debt.php</link>
			<description>
				<![CDATA[				<section id="setup-blurb">
Note: A friend of mine recently co-authored a book,  <a href="https://www.amazon.com/Managing-Technical-Debt-Development-Engineering/dp/013564593X/ref=sr_1_1?keywords=managing+technical+debt&qid=1559227042&s=gateway&sr=8-1">Managing Technical Debt</a>, and if you're a developer or architect wrangling with instability or quality issues, it's a really great read.  They kindly asked me to contribute a side bar.  In this post, I'm poking at the limits of the standard definition, but I think they've got some great answers/insights in their book.
</section>


<p>
At first, the metaphor of <a href="https://en.wikipedia.org/wiki/Technical_debt">technical debt</a> seems so crisp and clear.  It's the perfect way to explain to your manager, product owner, or fellow developers the impact of all the copy-and-paste code you see in the code base or those horrible thousand-line functions nested 8 levels deep.  
</p>

<p class="indentableSubtle">
"In order to make that last release, we had to cut a few corners.  These cut corners are like 'debt' , and at some point we'll have to pay it back or we'll go bankrupt"
</p>

<p>
At this level, the <a href="https://martinfowler.com/bliki/TechnicalDebt.html">concept of technical debt</a> is absolutely effective.  Everyone gets it.  Just like any individual person, a software development team too needs to manage their "finances".  Sure, it may be ok to take out a line of credit to "build that addition" (or whatever), but as a standard way to operate it's not sustainable.  Pay now, or pay later.
</p>

<p>
So what's the problem?  
</p>

<p>
The devil is in the details, as they say, and although the metaphor of "debt" makes a lot of sense at the conceptual level, things get fuzzy real quick when you try to put your finger on exactly what <i>it</i> is.  This matters because <b>when it's difficult to define something, it's really tough to measure or manage it</b>, and this is exactly what we want to do with technical debt.  Once we accept that we have this "debt" in our systems, we naturally want to know how much we have, whether that's a lot, and how long we have until the bank repossesses our system.  The trouble is, there are so many different interpretations of technical debt, this is anything but trivial.
</p>

<p>
Sure, there is a consensus definition that seems tenable and intuitive at a high-level, but it frays with just a little scrutiny.  To see what I mean, let's start with the standard definition of technical debt. Paraphrasing from the <a href="https://en.wikipedia.org/wiki/Technical_debt">Wikipedia</a>:
</p>

<p class="indentableSubtle">
Technical debt is the cost of additional rework caused by choosing an easy solution now instead of a better approach that would have taken longer.
</p>

<p>
The first thing to note is that taking on debt is a decision we make.  A deadline looms, and so we consciously <i>choose</i> expedience over "doing the right thing".  We've all been there, and calling this "debt" is an apt description.  
</p>

<p>
But wait.  <b>Is it always a choice?</b>  What about those cases where we <i>unknowingly</i> implement the inferior solution?  Maybe we were new to the language or framework, and had no idea there was a better way.  Or maybe we were just genuinely clueless!  Martin Fowler considers this technical debt also, but classifies it as <a href="https://martinfowler.com/bliki/TechnicalDebtQuadrant.html">inadvertent debt</a>.  Ok, so now tech debt isn't necessarily a <i>conscious</i> choice, but it <i>is</i> still something we do to ourselves...
</p>

<p>
But maybe not (!), because it's easy to think of cases where <b>it wasn't our doing</b>.  For example, what if we were moving along merrily and then some underlying framework we were using changed, and we now need to upgrade or migrate (<a href="https://stackoverflow.com/questions/34114593/angularjs-vs-angular">AngularJS</a> anyone?). Some call this <a href="https://hackernoon.com/there-are-3-main-types-of-technical-debt-heres-how-to-manage-them-4a3328a4c50c">accidental</a> debt - it's something we have to address and it'll get worse the longer we wait, but it definitely wasn't a choice - it happened <i>to us</i> because of age or decay.  But again we're further away from the original definition...
</p>

<p>
And then is tech debt only about maintainability?  Could it be related to any <a href="https://en.wikipedia.org/wiki/Non-functional_requirement">"ility"</a>?  For example, if I quickly bang out some naive/slow algorithm but add a <span style="font-family: courier new">// TODO fix this to make it faster</font></span>, is that tech debt?  It seems to fit the criteria of expedience over doing what's "right" in the long run, but it's about performance and not maintainability.  And if this too is technical debt, why couldn't we consider some sub-optimal solution for security or resilience tech debt as well (e.g. the system doesn't handle failure now, but could with some rework)?  And while we're at it, is lack of code comments tech debt?  Or lack of documentation in general?  And so on and on...
</p>

<p>
Maybe this seems like pedantic nit-picking...but that's kind of the point!   As we ask reasonable questions about what technical debt is and what it is not, we stretch at the seams of the concept in general, and it begins to unravel to the extent that it seems like <b>either everything is tech debt, or nothing is tech debt</b> (a position held by <a href="https://medium.com/@kellan/towards-an-understanding-of-technical-debt-ae0f97cc0553">some</a>) and at this point the entire term can seem almost vacuous.  
</p>

<p>
So where does this leave us?  I think there are a few options.  One is to just admit that the more we allow for new and different edge cases of technical debt (e.g. accidental debt, inadvertent debt, reckless, etc.), the more we water down the entire concept in general until no one really knows what it is, and it begins to lose its effectiveness as a metaphor.  Just hold the line on the original definition and we'll be better off.
</p>

<p>
Another option though is to see it as <i>just</i> a metaphor, and then at a backlog/management level, treat all work as simply stuff that needs to get done to improve the system.  Whether a given work item is there because we cut a corner a few months ago or because our version of Java is being sun-setted next month doesn't matter - it's just all work we need to prioritize and then do.  Basically, use "technical debt" as an explanatory term, but at a practical level just manage it on your backlog with everything else.
</p>


<p>
In the end, I'm curious what you think.  Am I missing a key distinction?  How do you use the concept of technical debt?  Is it helpful?
</p>				]]>			</description>
			<pubDate>Wed, 29 May 2019 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2019/the-trouble-with-tech-debt.php</guid>
		</item>
		<item>
			<title>First Ask Questions</title>
			<link>http://www.bennorthrop.com/Essays/2018/unfolding-the-architecture-first-ask-questions.php</link>
			<description>
				<![CDATA[				<style>
  li {
    margin-bottom: 15px;
  }

</style>
<p>
As a developer, you often find yourself in a situation where someone is describing some new system to be built, and you're trying to wrap your head around exactly what "it" is.  Maybe it's a client with a potential new project, or maybe just a friend with another one of his "can't-miss" ideas for a new app.  Regardless, the goal is essentially the same: through a simple conversation, you want to <b>quickly size things up</b> and help them figure out (a) whether it's technically feasible, and (b) if it is, how it could be built.  
</p>

<p >
Early in my career, I'd usually cut right to the chase (or so I thought).  I'd get a basic sense for what the system needed to do, and then I'd start sketching out my ideas for the tech stack:
</p>
<p class="indentableSubtle">
    "Ok...it's a B2C commerce web app here...pretty standard...so probably React, NodeJS, and Mongo." <then draw some boxes and lines>
</p>
<p>
Or whatever.  The point is, as an opening gambit, this wasn't very effective.  While it might convey some level of confidence to the "business" owner that I was a capable technologist (I mean, hey, I threw out some good <a href="http://www.bennorthrop.com/Essays/2015/slaves-to-fashion.php">buzz words</a>), it wouldn't actually buy me much in terms of a real understanding of the risks, constraints, and goals that should drive the architecture.  If the project did come to fruition, I'd quickly realize that my "design" had some serious holes, and I'd have to scramble to fill them in.    
</p>
<p>
(As an aside, I think this is a common pitfall for developers.  Although we like to fashion ourselves as "problem solvers", too often we live up to only the second half - we're just "solvers".  The exact "problem" that we're addressing isn't always clear, well formed, or even <a href="https://medium.com/@george3d6/imaginary-problems-d4f2921bd1b8">real</a>, because we were too quick to jump in with our own ideas and assumptions, instead of slowing down to first listen and understand.)
</p>
<p>
Nowadays, with a little more experience, I try (at least in these early conversations) to <b>only ask questions</b>, and hold off on proposing anything too early.  If <a href="http://files.catwell.info/misc/mirror/2003-martin-fowler-who-needs-an-architect.pdf">architecture is about the hard things</a>, my goal is to hunt down what these things are.  Only when I've mapped out the terrain do I try to map out a route forward.  
</p>
<p>
For whatever it's worth, here are a few questions I start with:  
</p>
<p>
<ol>
<li>How many <b>users</b> (or consumers) are there, how much will they use it, and are there patterns (or spikes) to their usage?  
</li>
 
<li>What <b>devices</b> would access the application with (e.g. mobile, desktop, voice, etc.)?    
</li>
 
<li>What is the <b>sensitivity</b> or importance of the functionality or data that this system provides or exposes?  For consumers, is authentication alone sufficient, or does access to certain pieces of the application need to be controlled or managed (i.e. access control)?    
</li>
 
<li>Is any <b>data</b> persisted?  If so, what type of data is this (structured, unstructured, etc.)? How much is there? How does the data get into the system (e.g. user entry, telemetry, etc.)?  Is data created, read, updated, or deleted?  How important is integrity or consistency?  
</li>
 
<li>What other systems does this system need to interact or <b>integrate</b> with?  What is the nature of the communication (e.g. real-time, batch feeds, etc.)?  What type of security is necessary?    
</li>
 
<li>On what <b>hardware</b> does the system run?  Is it a kiosk, embedded system, server-based, etc.?  Can it be hosted on a public cloud, or does it need to be managed internally?  Who owns and manages the machines on which the system runs?  How will it be deployed?  How will updates be delivered?  
</li>
 
<li>How <b>critical</b> is the application?  Can any downtime be tolerated, and if so, when?  What is the cost of downtime?    
</li>
 
<li>Who will <b>maintain</b> the application when it's in production?  What tools will they have available to monitor or verify the health of the system?  Will they be able to
</li>
 
<li>What is the <b>timeline</b> for which the system needs to be built (or new features need to be delivered)?  What is the development capacity?  
</li>
</ol>
 
<p>
In the end, this is software, and so there are innumerable facets, variables, and complexities to explore (and that could trip us up), and so there are plenty of other questions that might need to be asked.  These are just some starting points, but where the conversation flows from there depends on the system.  
</p>				]]>			</description>
			<pubDate>Thu, 06 Sep 2018 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2018/unfolding-the-architecture-first-ask-questions.php</guid>
		</item>
		<item>
			<title>The Reality of Reuse</title>
			<link>http://www.bennorthrop.com/Essays/2018/the-reality-of-reuse.php</link>
			<description>
				<![CDATA[				<p>"Don't reinvent the wheel", they always say.  And at first blush, it all seems so obvious. If you spend the time to build something once, why not reuse it?  There's no down side, right?  Well, it's not that easy.  As a grizzled <a href="http://www.bennorthrop.com/Essays/2016/reflections-of-an-old-programmer.php">"old" programmer</a>, I've seen organizations fall victim to this spurious ideal over and over again, paying the dues of up-front design and development, but never reaching the promise land of massive ROI via reuse. In fact, in my opinion, our <b>overly optimistic expectation for the benefits and ease of reuse</b> is one of the most pervasive and pernicious traps in software development.</p>

<p>The root of the problem, I believe, is what <a href="https://en.wikipedia.org/wiki/Daniel_Kahneman">Daniel Kahnaman</a> calls <a href="https://jeffreysaltzman.wordpress.com/2013/04/08/wysiati/">What You See Is All There Is</a>., which explains, in a nutshell, that we're hard-wired to want to make decisions quickly, using only the evidence we have at hand and some basic heuristics.  Slowing our thinking down would take time and discipline, and so instead we try to <a href="https://en.wikipedia.org/wiki/Attribute_substitution">substitute</a> complex problems we don't fully understand for simple ones we do.  </p>

<p>In the case of reuse, our intuition is simple and strong, represented by that hard-to-shake physical world analogy of software as a "wheel" not to reinvent.  And it's this comfortable mental model that we often fall back on when making decisions about reuse.  The problem is that this <b>basic intuition about reuse is flawed</b>, or at least woefully incomplete.  Let's see how...</p>

<p><i>(A quick caveat:  my argument here is around large-scale reuse, not at the method or function level.  I'm completely down with <a href="http://wiki.c2.com/?DontRepeatYourself">DRY</a> at the lower level of granularity.  Also I'm thinking of reuse as the leveraging of some service/library/etc. that was built internally vs. acquired externally.  I'm not recommending building your own JS MVC framework!  Ok, now back to the originally scheduled post...)</i></p>

<h3>The Intuition</h3>
<p>Imagine there is a system, A, that contains some logic, C, within it.  Soon, a new system, B, is to be built, and this system too needs the same basic logic, C.  </p>

<img class="center" src="/Essays/2018/reuse-1.png" width="300" style="margin-bottom: 15px" />


<p>Now it stands to reason that if we just split C out from A, it could then be used by B without the need to re-implement.  The savings is therefore equal to the cost of one instance of C - i.e. it only had to be built once, and not again for B.</p>

<img class="center" src="/Essays/2018/reuse-2.png" width="300" style="margin-bottom: 15px" />

<p>Further, as more systems are identified to have this same common code, the benefits of this extraction and reuse will be extended to those systems as well in a linear fashion, such that for every new system that reuses C instead of re-implements it, there is another savings equal to the implementation cost of C.  </p>

<p>Again, the logic here seems simple and seemingly unassailable - why would any organization choose to build multiple instances of C rather than just build it once and then reap the benefits of reuse.  The problem is that there's more to this picture, and what can look like slam-dunk ROI up front can turn into an costly straight-jacket down the road.  Here are a few ways in which the basic intution of reuse breaks down...</p>

<h3>The Reality</h3>
<p>The first problem is that of <b>extraction</b>.  Our intuition is that C should snap apart from A like a piece of lego - nice and easy. The reality, however, is that disentangling common code can be a little like pulling a piece of spaghetti from your bowl of pasta, only to find that the entire dish is just one long noodle.  Of course it's not usually that bad, but in code, there are lots of hidden dependencies and connections, and the initial conception as to the scope of C grows as you begin to unwind it.  The effort is almost never as easy as you expect.</p>

<p>
Moreover, almost always, C needs other things to do its job (e.g. other libraries, utility functions, etc.).  In some cases these are shared dependencies (i.e. both A and C need them) and some cases not.  Either way, the simple picture of A, B, and C can begin to look less so.  For the sake of this example, let's assume both A, B, and C each use a common library, L.</p>

<img class="center" src="/Essays/2018/reuse-3.png" width="300" style="margin-bottom: 15px" />

<p>Another problem is that of <b>variation</b>: different consumers of C will often have slightly different requirements for what it should do.  For example, there may be some function in C that needs to behave slightly differently if A called it than if B did.  A common solution for these cases is parameterization: the given function takes some parameter which lets it know how to behave given who called it.  This can work, but it increases complexity of C, and the logic gets messy as well, as the code gets riddled with if blocks like "if called from A then do this block of logic".  </p>

<img class="center" src="/Essays/2018/reuse-4.png" width="300" style="margin-bottom: 15px" />

<p>Now even if C <i>is</i> a case of perfect reuse for A and B, this type of variation almost always is necessary as new systems, say D and E, come along.  They may want to use some of C the way it is, but then need other parts to change in subtle or not-so-subtle ways.  Again, each new accommodation that needs to be made within C represents extra complexity, and so what used to be something fairly easy to grok from the perspective of a developer using it, now becomes a lot trickier as C morphs into something that must satisfy the needs of D, E, F, and so on.  Which leads to the next problem...</p>


<p>As this complexity increases, developers have a tougher time groking what C does, and how to use it.  For example, a developer of A might not understand some parameter for a function of C, since it's only relevant for systems E and F.  In most cases, some level of API <b>documentation</b> is necessary (maybe <a href="https://swagger.io/">Swagger</a>, Javadoc, or more) to explain the inputs, outputs, exceptional conditions, and other SLAs/expectations.  And while documentation in general is a good thing, it's not without its problems (e.g. keeping it up to date, etc.).</p>

<img class="center" src="/Essays/2018/reuse-5.png" width="300" style="margin-bottom: 15px" />

<p>Another implication of increased complexity is that it can be harder to maintain <b>quality</b>.  C now serves many masters, and so there are a lot of edge cases to test.  Further, since C is now used by many other systems, the impact of any given bug is amplified, as it can pop up in any or all of the consuming systems.  Often, for any change to C, it's not enough to test just that shared component/service, but some level of regression testing should be done as well for A, B, D, and all the other systems that depend on it (whether the change to C is actually used by that system or not!).</p>

<p>Again, since we're talking about reuse at a non-trivial scale, it's probably the case that C will need to be developed by a separate team of developers, which can lead to a <b>loss of autonomy</b>.  Separate teams usually have their own release schedules, and sometimes their own development processes.  The obvious implication is that if A's team needs some enhancement in C, it probably needs to work it through C's process - i.e. a champion of A needs to provide requirements, advocate for its priority, and help with the testing.  In other words, team A is no longer in control of its own destiny with respect to the functionality that C implements - it is dependent on the team that delivers C.  </p>

<img class="center" src="/Essays/2018/reuse-6.png" width="300" style="margin-bottom: 15px" />

<p>Lastly, when C is upgraded, by definition there are now <b>different versions</b>.  Depending on the nature of the reuse, this can present different issues.  In the case of build-time reuse (e.g. library), the different systems (A, B, etc.) could stick with their working version, and choose to upgrade when optimal.  The downside here is that there are different versions of C in the wild, and it's not unlikely that one bug might lurk in each of the versions, and need to be patched in each.  In the case of  run-time reuse (e.g. microservice), C would either have to support multiple versions of its API in one instance or it could just upgrade without consideration of backward compatibility and thus force A and B to upgrade along with it.  In either case, the robustness and rigorousness of the processes and organizations to support this reuse are significantly increased.  </p>

<img class="center" src="/Essays/2018/reuse-7.png" width="300" style="margin-bottom: 15px" />

<h3>Conclusion</h3>
<p>In the end, my point is <i>not</i> that large-scale reuse should be avoided, but rather that it's not as easy as our intuition suggests.  Reuse is hard, and while it may still deliver benefits that outweigh its costs, those costs need to be realistically considered and discussed up front.</p>

<p>Even after careful consideration, if large scale reuse <i>is</i> the right course of action, there's still a decision as to the nature of reuse.  My experience tells me to be careful of the dependency arrows.  Reuse where the "reuser" is in control is almost always easier to implement and manage than reuse where the reusable asset calls the system.  In the example above, having C be a library or microservice puts A and B in the driver seat, and this, in my opinion makes for quicker implementation and less management/coordination in the long run. </p>

<p>Flipping the dependency arrows, and making C a framework or platform, changes the onus of control.  Now A and B are beholden to C.  This type of reuse is not only more difficult to build (and get right), but results in greater lock-in down the road (i.e. A and B are totally dependent on C).  A great <a href="https://stackoverflow.com/questions/148747/what-is-the-difference-between-a-framework-and-a-library">adage</a> is that "a library is a tool, a framework is a way of life".</p>

<img class="center" src="/Essays/2018/reuse-8.png" width="300" style="margin-bottom: 15px" />

<p>
In the end, I'd love to hear your feedback or experience with large-scale reuse.  When does it work out and when does it fail? </p>

				]]>			</description>
			<pubDate>Thu, 22 Mar 2018 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2018/the-reality-of-reuse.php</guid>
		</item>
		<item>
			<title>Unclosed Loops and Developer Frustration</title>
			<link>http://www.bennorthrop.com/Essays/2017/unclosed-loops-developer-frustration-and-the-zeigarnik-effect.php</link>
			<description>
				<![CDATA[				<p>
Tolstoy <a href="https://en.wikipedia.org/wiki/Anna_Karenina_principle">once wrote</a>, "all happy development teams are alike; every unhappy development team is unhappy in its own way".  And after <a href="http://www.bennorthrop.com/Essays/2016/reflections-of-an-old-programmer.php">20 years as a programmer</a>, I can attest to at least one sure-fire route to unhappiness:
</p>

<p class="indentableSubtle">
    It's the beginning of the sprint.  Everything's been planned, estimated (if that's how you roll), and assigned.  You have a few features on your plate, and are eager to get going.  Starting with the most critical one, you dig in for a day, get a plan together for how to tackle it, and begin coding.<br/><br/>Another day passes and you get about halfway through when the project manager swings by your desk.  "Hey", he says, "I know you've already started, but a business priority has changed, and we need you to work on this different feature instead.  Finish this new one off now, and then you can get back to your original work".
</p>

<p>
I'm not sure about you, but this drives me freaking crazy (at least it does when it happens often).  But should it?  I mean, I'm being paid by this company, and it's up to them to set their own priorities, right?  If they decide there's more value in a different feature, that's their call.  Further, I'll get back to the original feature eventually, and if I don't, who cares - I learned a few things in the process of digging in, and probably have a better grasp of the application as a result.  What reason do I have do be frustrated?  And yet I am...
</p>

<p>
This internal tension has plagued (or at least puzzled) me forever.  <b>Why do I hate leaving tasks unresolved so much?</b>  And I think its not just me - most of my colleagues seem to get just as frustrated when it happens to them.  But why?  Recently, while reading the book <a href="http://www.bennorthrop.com/Essays/2016/reflections-of-an-old-programmer.php">Irresistable</a>, I found an explanation.
</p>

<p>
In psychology, there's a well known cognitive bias called the <a href="https://en.wikipedia.org/wiki/Zeigarnik_effect">Zeigarnik effect</a>.  It states, simply, that an incomplete or interrupted task will be remembered better than a complete one.  The phenomenon was coined by Bluma Zeigarnik, a psychologist who noticed that waiters had better recollections of orders that were unpaid.  As soon as an order was completed, the waiter effectively flushed it from memory.  In her paper <a href="http://codeblab.com/wp-content/uploads/2009/12/On-Finished-and-Unfinished-Tasks.pdf">Finished and Unfinished Tasks</a>, she explains:
</p>

<p class="indentableSubtle">
  "When the subject sets out to perform the operations required by one of these tasks, there develops within him a quasi-need for completion of that task. It is like the occurrence of a tension system which tends towards resolution. Completing the task means resolving the tension system, or discharging the quasi-need. If a task is not completed, a state of tension remains and the quasi-need is unstilled."
</p>

<p>
This hits the nail on the head for me.  When I start development of a new feature, there's a non-trivially strong force within me that wants to drive it to completion.  If I'm asked to table that feature in favor of something different, my brain can't completely let go of the original task and so I can't fully focus on the new task at hand. The details of the original task are still churning in some background process in my brain.
</p>

<p>
Further, my guess is that the Zeignarnik effect is probably cumulative as well.  The <b>more tasks interrupted, the greater the tension and frustration</b>.  And for some, this is the rule rather than an exception.  You get into work intending on finishing off some feature, but then get pulled into a meeting to discuss something different, and then get pulled out of that meeting to work on a production defect, and so on until the day ends and almost nothing was fully resolved.  Ultimately frustrating.
</p>

<p>
Adjustments can (and probably should) be made in an organization to avoid this effect, since the effectiveness, mental clarity, and possibly even sanity of their developers depend on it.  First, of course, we should strive to limit interruptions and let developers close open loops before forcing new ones upon them.  Many teams have already started doing this through the adoption of <a href="https://www.guru99.com/agile-vs-kanban.html">Kanban</a> and <a href="https://www.atlassian.com/agile/wip-limits">work-in-progress limits</a>.  Additionally though, in environments where interruptions are rampant, perhaps tasks could be designed to be as fine grained as possible, allowing developers to finish something before being pulled off to work on the next.  Lastly, it's possible the best solution might just be to strive to overcome our innate mental wiring - when you get frustrated over switching away from a task, just acknowledge it's just the Zeignarnik effect, and do what you need to do.
</p>

<p>
Anyway, I'd be interested to hear about your experiences.  Is the Zeigarnik effect real, and does it cause frustration?  What do you or your team do to address it?
</p>




				]]>			</description>
			<pubDate>Mon, 16 Oct 2017 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2017/unclosed-loops-developer-frustration-and-the-zeigarnik-effect.php</guid>
		</item>
		<item>
			<title>Batch Jobs in Clustered Environments</title>
			<link>http://www.bennorthrop.com/Essays/2017/batch-jobs-in-clustered-environments.php</link>
			<description>
				<![CDATA[				<p>
As much as we'd prefer to do everything in real time, there's often a need for <a href="https://en.wikipedia.org/wiki/Batch_processing">batch processing</a>.  Performance is the most common driver, but sometimes there are also business reasons as well.  
</p>
<p>
As an example, maybe your central application is some transactional web app, and there's some data cleanup you need to do at the end of the day - some user transactions, say, that are helpful to keep for a day, but can be purged at midnight.  Assuming this is a reasonable candidate for a batch job (bear with me), the question then is, <b>what is this batch job</b>?  What I mean is, is it external to the transactional system from which the data was created, or is it embedded within it?
</p>
<img class="center" src="http://www.bennorthrop.com/Essays/2017/batch-job-internal-vs-external.png" />
<p>
It's probably obvious that, from a scalability and performance perspective, the best solution is the external one, since any resources (CPU, memory, etc.) consumed by the batch job are not subtracted from the core transactional system.  (though, yes, they both share the DB...so maybe not the best example!)
</p>
<p>
But is there ever a case where it makes sense to run batch jobs <i>within</i> a transactional system?  Though an <a href="http://www.bennorthrop.com/Essays/2009/what_is_good_architecture.php">architectural purist</a> would probably say "no", there can be a few advantages to this approach:

<ol>
  <li><i>Simplicity</i>:  Depending on your organization/environment, procuring a machine and resources to run batch jobs can be a challenge, as can be the management of the scheduling and execution of these processes.  Sometimes the easiest thing to do is just include the batch processes in the thing (i.e. deployable unit) you have.  For big organizations (where bureaucracy and overhead are high), this is probably the path of least resistance. </li>
<br/>

  <li><i>Code Reuse</i>: Often times, the batch job needs to do some of the same types of "stuff" the transactional system does.  For example, it may query the same tables, shove them into the same domain model classes, and execute the same business logic.  To avoid code duplication, these code assets would need to be externalized to some common library for both the batch job and transactional system to leverage, and the work of extracting code into new libraries is non-trivial.</li>
</ol>

<p>
If you do decide that in your case, these advantages of running batch jobs within a transactional system outweight the drawbacks, then it's important to note a crucial snag: clustering. When the batch job is embedded in the transactional system, and there are multiple instances of the transactional system deployed in a cluster (for either scalability or reliability/availability), then some mechanism needs to be in place to ensure that the batch job gets kicked off on one and only one node in the cluster.  
</p>

<img class="center" src="http://www.bennorthrop.com/Essays/2017/batch-job-clustering.png" />

<p>
There are a few possible solutions to this problem, some more reliable/elegant than others.  One naive option is to just <b>configure one node</b> in the cluster to be the one that runs the batch job (e.g. "if hostname='server1.acme.com' then run batch job"), but this has the obvious flaw that if this server is down, another node in the cluster wouldn't know that it needs to pick up the slack.  JBoss has a more robust form of this solution with its <a href="https://developer.jboss.org/wiki/HASingletonDeployer?_sscc=t">HASingletonDeployer</a>.  
</p>

<p>
Another <a href="https://stackoverflow.com/questions/6771541/java-batch-job-in-cluster-environment-resolved">workable option</a> is for some <b>external scheduler</b> to kick off the batch job, with a request (either via MQ or even HTTP) to the transactional system.  This option is workable, but has some downsides - the transactional system needs to expose endpoints (or consumers) to listen for requests to run the batch job and the remote scheduler needs to be sophisticated enough to know that if the job wasn't picked up (or run successfully) on one node, the request needs to be sent to the other.
</p>

<p>
Probably the best solution for this problem I've found, for the Java side at least, is a library called <b>ShedLock</b>.  It's laser-focus-designed specifically to solve this exact problem.  All nodes in a cluster would be <i>able</i> to run the batch job, but they would use a central database to obtain a lock before running it, where only the node that has the lock runs it, and the rest skip it.  The configuration is super easy, and rather than regurgitate already great documentation, just check out their <a href="https://github.com/lukas-krecan/ShedLock">github</a>.  
</p>

<p>
Anyway, this was a problem that we recently confronted, and since I didn't find a ton of good content out there I figured I'd write this out.  Hope it helps someone!
</p>
				]]>			</description>
			<pubDate>Tue, 10 Oct 2017 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2017/batch-jobs-in-clustered-environments.php</guid>
		</item>
		<item>
			<title>Code Review Best Practices</title>
			<link>http://www.bennorthrop.com/Essays/2017/code-review-best-practices.php</link>
			<description>
				<![CDATA[				<section id="signature" style="background-color: #ffffe6">
<i>Note: I wrote this years ago while working for a company that no longer exists, so I thought I'd post it on my site for whatever it's worth.</i>
</section>

<p>
From the Wikipedia, a <a href="https://en.wikipedia.org/wiki/Code_review">code review<a> is defined as "a systematic examination of computer source code intended to find and fix mistakes overlooked in the initial development phase, improving both the overall quality of software and the developers' skills". A great deal of <a href="#evidence">evidence</a>, both empirical and anecdotal, has supported the effectiveness of code reviews, and most would consider them to be a best practice in software development.  In general, the main benefits are:
</p>
<ul class="spaced">
  <li>Improve internal quality of the system (e.g. maintainability, extensibility, etc.)</li>
  <li>Improve external quality of the system (e.g. reduce bugs, improve quality)<br/></li>
  <li>Facilitate the transfer of critical project-related knowledge amongst team members.<br/></li>
  <li>Provides a format for the mentoring of junior developers.<br/></li>
</ul>

<p>Some less obvious or widely touted, but equally valuable benefits from code reviews are:</p>
<ul class="spaced">
<li>Spot opportunities for re-use, thereby reducing code redundancy.<br/></li>
<li>Enforce consistency in development practices and application of coding styles and patterns.<br/></li>
<li>Provide managers with a measure of progress during the construction phase.<br/></li>
<li>Keep developers motivated to perform higher quality and quantity work via a peer pressure mechanism.<br/></li>
</ul>
</p>

<p>
Fagan Inspections are typically viewed as the canonical form, however code reviews can come in a number of flavors:
<ul class="spaced">
<li><i>Fagan Inspection</i>: The most formal and rigorous of code review techniques. Involves the public review of one developerâ€™s source code by a set of reviewers, facilitated by a moderator.<br/></li>
<li><i>Walk-through</i>: A less formal, perhaps impromptu meeting where developers read through code in real time with the intent of detecting errors.<br/></li>
<li><i>Pair Programming</i>: A practice whereby two developers work together at one keyboard. Note I'm not a huge fan of <a href="http://www.bennorthrop.com/Essays/2013/pair-programming-my-personal-nightmare.php">pair programming</a>.<br/></li>
<li><i>Pass-around</i>: Code is distributed and reviewed independently by developers, and comments are then provided to the author.<br/></li>
<li><i>Automated Review</i>: Code is mechanically inspected by static source code analysis tools.<br/>
</ul>

Note that each with their own distinctive levels of formality, format, costs, and benefits. The type that is â€œrightâ€ for any given organization depends on that organizationâ€™s unique goals, constraints, and capabilities. For example, the code review process appropriate for an early-stage start-up in a release-or-perish situation would be very different from that of a more mature, stable organization developing mission critical medical-device software. 
</p>

<p>
Recognizing this, that the â€œfitâ€ of the code review process in an organization is critical to its success, it would be unwise to rigidly recommend one process for developers to dogmatically apply across all clients. Instead, what is needed is a code review process that is effective â€œout-of-the-boxâ€ for our typical projects and customers, but ultimately adaptable, acknowledging that no project or customer is ever really â€œtypicalâ€. Additionally, the process must also be relatively familiar to most developers (e.g. similar to Fagan, etc.), must not be overly demanding or time intensive, and must mesh well with other SIP processes (e.g. RUP, Scrum, etc.). The process defined below aims to achieve each of these goals.  
</p>

<h3>Process</h3>
<p>
The diagram below illustrates the baseline process for a code review. Note that for the purposes of this process, there are just two roles â€“ authors and reviewers. Typically, the set of reviewers will consist only of developers on the project team, but could also include other project stakeholders (e.g. for validating business logic, etc.). 
</p>


<img class="center" src="http://www.bennorthrop.com/Essays/2017/code_review_process.gif" />

<p>
<b>1. Identify Files:</b> After being informed of the segment of code to be reviewed (see "What code to review"), the author identifies a set of source files (e.g. configuration files, UI code, scripts, etc.) and possibly requirement or design documents (if they are germane to the review) and emails this list to all reviewers along with any caveats (e.g. "don't look at method X, because it's not finished", etc.). This list of files should take no more than one hour to compile and should be sent at least 4 days prior to the meeting, giving reviewers enough time to inspect the code. 
</p>

<p>
<b>2. Review Code:</b> Upon receiving the list of files from the Author, each reviewer reviews the code on his own. Among other things, reviewers are looking for functional correctness, style, clarity, extensibility, reusability, and performance. For each project, a code review checklist can be created (in the SDG or on the wiki) and then referenced by the reviewer to ensure that code adheres to the project-specific conventions and standards. The author records all issues, suggestions for improvement, or kudos found in the code, organizes them by file, and then emails this feedback to the author at least one day prior to the meeting.  Reviewers should cap the amount of time spent reviewing code at one hour (data suggests that there are diminishing returns after 60 minutes, and investing more than an hour is too taxing on the individual Reviewer â€“ he has his own work to do too!). 
</p>

<p>
<b>3. Review Feedback:</b> After receiving all feedback from Reviewers, the Author should examine each comment and determine (a) whether the comment should be addressed (e.g. fixed, refactored, etc.) and (b) whether the comment merits extra discussion among the group. For example, feedback about a missing method comment is easily addressable (just add the comment!) and doesnâ€™t warrant a full discussion. On the other hand, a question about a coding convention may indicate the lack of a standard, and should be discussed to garner consensus. The author should then compile a list of all comments from the Reviewers, mark those comments that need to be discussed, and print or email a copy for each Reviewer prior to the meeting. 
</p>

<p>
<b>4. Discuss Code:</b> Only when the Reviewers have examined the code and the Author has filtered the list of items to discuss should everyone get together and talk. At the meeting, the Author facilitates the meeting, stepping through each discussion item and making notes of any resolutions or decisions. The meeting should move briskly, but should not be rushed â€“ good, substantive discussion is the goal, and this takes time. As a rule of thumb, the meeting should last no longer than one hour. Any items not discussed or resolved should be tabled for another meeting or figured out independently by the Author or tech lead. Meetings that last over an hour typically leave participants feeling frustrated and less interested in doing a code review again. 
</p>

<p>
<b>5. Implement Changes: </b>Within a few days of the meeting, the Author cycles through the list of comments from the review and makes changes to the code where appropriate. In some cases it is useful to post the feedback, resolutions, or decisions to a wiki, but only if there is time (this is an agile process!). 
</p>

<h3>Best Practices</h3>
<p>
The following practices have been proven to be generally helpful when performing code reviews: 
</p>

<p>
<b>What code to review:</b> In general, the projectâ€™s technical lead is the most appropriate person to select the code to review, however the project manager or team as a collective could decide as well. When selecting code to review, the following general rules should be considered: 
<ul>
  <li>
    The first review of any project should target a senior developerâ€™s code, setting the tone that no developer writes perfect code and any developer can find valid issues in any other developerâ€™s code.
  </li>
  <li>
Critical or risky pieces of code (e.g. key business logic, integration points, reusable libraries) 
should take precedence over non-critical, safer pieces of code.
  </li>
  <li>
Over the course of a project, each developer should have their code be reviewed. No one on the team should be absolved, neither the most junior nor the most senior.
  </li>
  <li>
A segment of code to be reviewed should include no more than 10 files.
  </li>
</ul>
<p>
Use static code analysis tools prior to review: Static code analysis tools like PMD and Checkstyle can be extremely useful in rooting out syntactic and stylistic issues in the code more quickly than a manual review. See automated review for standard configurations and best practices. 
</p>

<p>
<b>Be careful of feelings:</b> Developers by their nature often feel quite attached to their work. Criticisms of code can easily be perceived as criticisms of the person, and so itâ€™s common that authors leave feeling hurt, angry, or scorned. Because of this, reviewers need to be keenly aware of the social component in code reviews, being careful to praise more than criticize, focus on the code and not the person, ask questions rather than make statements, and in general be tactful and build trust. As Karl Wiegers says, â€œbugs are the bad guy in the review, not the authorâ€. 
</p>

<p>
<b>Document coding standard: </b>Oftentimes code reviews will expose differences in opinion about coding standards, best practices, or patterns. These disagreements are extremely useful, as they are the first step toward consensus. In fact, code reviews are sometimes the only opportunities developers get to discuss and resolve such issues in the course of a development cycle â€“ and catching them quickly is helpful for ensuring coding consistency and reducing redundancy. As agreement is reached, however, it is important to document this in a knowledge repository (e.g. Wiki) or in an SDG, SAD, or SDP to ensure that the conflict can be quickly resolved in the future. 
</p>

<p>
<b>Find a management advocate:</b> In staff augmentation projects, garnering support from management is imperative - without it, the time spent cannot be justified (e.g. on time-sheets, etc.), developers will resist or thwart their adoption, and the practice will degenerate as other time pressures come to the fore. Oftentimes, managers will be supportive of a code review practice, however, when they are not, it is helpful to present the benefits (both intangible and hard data) and note that code reviews are a common, proven practice adopted by countless other mature software organizations. If support is not there, code reviews can still be on off hours (e.g. lunches, early mornings, etc.). 
</p>

<p>
<b>Assign a watch-dog:</b> Most developers know that code reviews are good for them, but like exercise or vegetables, they're easily neglected. Therefore, it's important to have one person responsible for managing, coaxing, and otherwise nagging developers about code reviews. This most often is the responsibility of the Technical Lead on the project, but could also be the project manager. 
</p>

<p>
<b>Review code every week:</b> A common practice is to review code prior to the completion of a requirement, using it as a code quality gateway that developers must cross through before a final check-in. While this seems ideal in theory, in practice the logistics often become intractibly complicated. In most development organizations, developers complete features at the same time (i.e. before the end of the iteration), and so each developer needs each other developer to review code at the very time that no one has any time to spare. First one review gets postponed, then another, and before you know it, there are no more reviews. A more sustainable practice is the rotating code review, where each week a different developer's code gets reviewed by the team. While this doesn't guarantee that code is reviewed at the  most optimal time, it does set a nice cadence and predictability to reviews, and helps install a healthy amount of fear in developers which in turn foments better coding practices (i.e. "it's possible that my code will be reviewed tomorrow, so I better write good code today"). In general, the more often you do code reviews, the easier, quicker, and more effective they will be. 
</p>

<p>
<b>Account for Code Reviews in Estimates:</b> Using the process defined above, code reviews require only a minimal time investment from each team member - about 5 hours for the author and 2 hours for each reviewer. In most cases, for both project work and staff augmentation, this time can be factored into the normal project schedule (like unit testing, documentation, etc.). 
</p>

<p>
<b>Hold review meetings over lunch:</b> A good way to ensure that code reviews don't intrude on normal, burn-downable project work is to hold the meetings over lunch. This also helps make code reviews less formal and a bit more fun. 
</p>

<p>
<b>Use code reviews as a vehicle to discuss architecture and design:</b> On many projects, there is no separate, allocated time for team members to discuss design or architecture issues. If this is the case, Code Reviews can serve this purpose as well. As a discussion about one particular method unravels into a more abstract discussion about performance or extensibility, it's useful to not cut this discussion short, as it can expose important gaps in the architecture or design. 
</p>

<p>
<b>Code reviews should not be performance reviews:</b> In the rare cases where project managers, business analysts, or even clients are involved in a code review, it's crucial for the tech lead to ensure that all participants understand that the code review should never be used as a way to assess the author's competence or performance - it should only be used as a tool for improving code and sharing knowledge. A good code review depends on open, honest dialog, and this is subverted when participants feel as though they are being critiqued. 
</p>

<h3>Resources</h3>
<ul>
<li><a href="https://www.google.com/url?q=https%3A%2F%2Fwww.safaribooksonline.com%2Flibrary%2Fview%2Fcode-complete-second%2F0735619670%2F&sa=D&sntz=1&usg=AFQjCNGo2WsTK5QIlfsZ8lS-qY2RiwNa2g" target="_blank">Code Complete</a>, Steve McConnel. <a href="https://www.google.com/url?q=https%3A%2F%2Fwww.safaribooksonline.com%2Flibrary%2Fview%2Fcode-complete-second%2F0735619670%2Fch21s03.html&sa=D&sntz=1&usg=AFQjCNHTZqbn6hc5bfSMODj8UU6ciyeOEg" target="_blank">Chapter 21.3: Formal Inspections</a></li>
<li><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.amazon.com%2Fexec%2Fobidos%2FASIN%2F0201734850%2Fprocessimpact&sa=D&sntz=1&usg=AFrqEzeG75sNIOmt-HTrxJpa0USsKDevOQ">Peer Reviews in Software: A Practical Guide</a>, Karl Wiegers (November 2002)</li>
<li><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.macadamian.com%2Findex.php%3Foption%3Dcom_techarticle%26task%3Dview%26id%3D1&sa=D&sntz=1&usg=AFrqEzcC_yizQoGwbdNEQXUOZUjKkQcHlw">Part of Your Complete Breakfast: Code Review is a Source of Essential Vitamins and Minerals</a>, Stephanie Lussier (2002)</li>
<li><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.codinghorror.com%2Fblog%2Farchives%2F000999.html&sa=D&sntz=1&usg=AFrqEzev7ZTApQ-OFCLmkojSctVv9HzrVg">Pair Programming vs. Code Reviews</a>, Jeff Attwood (November 2007)</li>
<li><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.developer.com%2Fjava%2Fother%2Farticle.php%2F3579756&sa=D&sntz=1&usg=AFrqEzf1U5U0QouuYSDTpYxoJN1bNMIfTg">Code Reviews without the Pain</a>, Robert Boque</li>
<li><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.processimpact.com%2Farticles%2Fseven_truths.html&sa=D&sntz=1&usg=AFrqEzeWdC8lyf9g67fjI7pHHXFDwxXcgA">Seven Truths about Peer Reviews</a>, Karl Wiegers</li>
<li><a href="http://www.google.com/url?q=http%3A%2F%2Ftoday.java.net%2Fpub%2Fa%2Ftoday%2F2006%2F08%2F17%2Fcode-reviews.html&sa=D&sntz=1&usg=AFrqEzdCaH7MCpOuuGV_KXUw8qSQaUCZsw">Code Reviews</a>, Srivaths Sankaran</li>
<li><a href="http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CDgQFjAA&url=http%3A%2F%2Fdrdenenelson.com%2Fpubs%2Fhicss-37-final.pdf&ei=q9CNT6-ZO8rw0gG_2MDGDw&usg=AFQjCNE5U4SDQdq9CQIR8ba0fcfaWwKTlw&sig2=f9nVhuTSCd2MVDfJg1w_cg">What Makes a Code Review Trustworthy?</a>, Stacy Nelson and Johan Shumann</li>
</ul>

<h3><a name="evidence">Evidence</a></h3>
<p>
In Code Complete, Steve McConnell describes specific studies that indicate that code reviews do indeed improve the overall quality a software system. Below are some of the more compelling statistics in favor of code reviews:
</p>

<ul>
<li>â€œIndividual inspections typically catch about 60 percent of defects, which is higher than other techniques except prototyping and high-volume beta testing.â€</li>

<li>â€œThe combination of design and code inspections usually removes 70-85 percent or more of the defects in a product.â€</li>
<li>â€œOn a project that uses inspections for design and code, the inspections will take up about 10-15 percent of project budget and will typically reduce overall project cost.â€</li>
</ul>

<p>
In addition, Karl Wiegers cites some compelling statistics from industry, in Seven Truths about Peer Reviews:
<ul>
<li>Hewlett-Packardâ€™s inspection program measured a return on investment of 10 to 1, saving an estimated $21.4 million per year. Design inspections reduced time to market by 1.8 months on one project [5].</li>
<li>Inspections contributed to a ten-fold improvement in quality and a 14 percent increase in productivity at AT&T Bell Laboratories [7].</li>
</ul>
</p>
				]]>			</description>
			<pubDate>Sun, 01 Oct 2017 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2017/code-review-best-practices.php</guid>
		</item>
		<item>
			<title>Should I Care about the Alexa Platform?  A Developer's View</title>
			<link>http://www.bennorthrop.com/Essays/2017/alexa-killer-app-a-developers-view.php</link>
			<description>
				<![CDATA[				<section id="setup-blurb">
Note: I recently gave a talk at <a href="http://pghtechfest.com/">Pittsburgh Tech Fest</a> on "Building Applications for the Alexa Platform".  The slides are on my site <a href="http://www.bennorthrop.com/alexa/PittsburghTechFest-Alexa-2017.pdf">here</a> and the sample code is on <a href="http://github.com/throp/mathwhiz">github.com/throp/mathwhiz</a>.
</section>


<img src="http://www.bennorthrop.com/Essays/2017/alexa.jpg" align="right" width="250" />


<p>Who knows what the future holds, but at least at this moment, it's safe to say that Amazon is killing it with <a href="https://developer.amazon.com/alexa">Alexa</a>.  Just 6 months ago, the total number of Echos, Dots, and Taps sold were around 5M and the number of skills available about 5K.  Today, both of those numbers have <a href="https://www.geekwire.com/2017/8-million-people-amazon-echo-customer-awareness-increases-dramatically/">almost doubled</a>, to 8.2 million devices and 10k skills, respectively.  What's more, it seems like every day now there's some new partnership, integration, or spin-off product to boast of - like the unveiling of the <a href="https://www.usatoday.com/story/tech/reviews/2017/05/09/amazon-echo-show-touchscreen-video-alexa/101448844/">Show</a> (voice + screen), the <a href="https://www.nytimes.com/2017/05/23/technology/amazon-echo-ikea-smart-homes.html">integration with Ikea</a>, or the release of the first <a href="https://www.wired.com/2017/05/htcs-squishy-new-phone-things-even-alexa/">built-in Alexa phone</a>.   Even the "just-plain-fun" stuff like the Seattle Mariner's <a href="https://www.geekwire.com/2017/alexa-get-us-wins-seattle-mariners-add-amazon-echos-private-suites-ballpark/">skill for their luxury boxes</a> or the <a href="https://www.youtube.com/watch?v=YvT_gqs5ETk">Silver</a> make it clear that Alexa has made it into the zeitgeist.</p>

<p>
So with everyone jumping on the Alexa bandwagon, the question for software developers is, should we jump on as well?  In other words, is it <a href="http://www.bennorthrop.com/Essays/2016/reflections-of-an-old-programmer.php">worth it</a> for us to invest in acquiring the knowledge and tools to build Alexa applications (or <a href="https://developer.amazon.com/alexa-skills-kit">skills</a>)?  And if we do, what would we build?  What are the "right" applications for this platform?
</p>

<p>
To answer these questions, it's probably helpful to first step back and take a look at what Alexa as a platform has going both for and against it.  In my opinion (for whatever that's worth), the matter of whether Alexa will rule the (voice) world is still open - there are reasons for both optimism and concern.  Here are my 2 cents...
</p>

<h3>What Alexa has going in its favor</h3>
<p>
As already covered, there are a ton of fun things happening in the world of Alexa recently.  It feels a bit like the early days of the internet or of IOS apps, where people are just throwing things at the wall to see what sticks.  There's a sense that it could be big, but it's not yet clear how or in what way.  And this uncertainty and openness is what's so exciting.  As developers, the opportunity is there to be a "first mover" - to make a huge impact with a relatively simple idea (if we can just come up with the right one!).  
</p>

<p>
Even better, the barriers to entry for building are pretty low.  Having been on the market for almost 3 years now, the platform is stable and rich, there's plenty of <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/getting-started-guide">great documentation</a>, a vibrant community, and ample choice from a tech stack perspective (with frameworks for <a href="https://github.com/amzn/alexa-skills-kit-java">Java</a>, <a href="https://github.com/amzn/alexa-skills-kit-js">Javascript</a>, and others).  Moreover, from a conceptual perspective, there's not all that much there.  Compared to what what you need to learn to build an IOS or web app, building a voice based application is a snap.  Sure, there's some new jargon (like "utterance", "intent", "slot", etc.), but with a few hours of study you're basically there.
</p>

<h3>What Alexa has going against it</h3>
<p>
Given all this (millions of users, plenty of room in the market, and a low cost to build), why wouldn't we all jump in?  Well, there are a few reasons to be wary, I think.
</p>

<p>
The first cautionary flag is the "stickiness" of Alexa.  It's true that everyone on your block just bought an Echo, but that doesn't mean they're actually using it.  A <a href="http://voicelabs.co/2017/01/15/the-2017-voice-report/">report from VoiceLab</a> recently showed that whereas for an Android or IOS app there's about a 12 percent chance that a user will still be using it in 2 weeks, the percentage chance for an Alexa skill is only at about 3 percent.  Further, of the 7,000+ skills available (at the time of the report), 69% have only zero or one review.  These stats seem consistent with what I hear anecdotally from friends and family.  The novelty of Alexa can wear off pretty quickly, and within weeks she can go relatively unused or might even end up relegated to the desk drawer.

<p>
If this is the case then, and there is indeed a retention problem, it begs the question: what's the reason?  Is it too few useful skills or something inherent to platform itself?
</p>

<p>
If it's about the quality of skills, then reason is probably obvious.  As of yet, there isn't a clear way for developers to monetize their creations - everything on Alexa is <a href="https://stackoverflow.com/questions/41218733/alexa-skill-monetization-possibilities-for-developers">free</a>.  As a consumer, this is great, but as a developer not so much.  Am I really going to sink dozens of hours into building a skill without a hope that there could be some (even meager) pot of gold at the end of my development hours?  I'm not so sure.  And this seems clear from even a quick perusal of the skills available.  There are a ton of banal "fact of the day" skills, but very few skills of any depth, quality, or creativity (though there are some).  Basically, it seems that developers are intrigued enough with the technology to dabble a bit, but without a proper incentive, very few have taken the time to build anything of real value.
</p>

<p>
It could also be the case, however, that the platform itself is to blame.  Many have voiced their concern about some of the <a href="https://goberoi.com/five-ways-amazon-can-attract-more-developers-to-the-echo-1cab8e930e83">inherent limitations of Alexa</a>.  Among the major <a href="https://www.reddit.com/r/amazonecho/comments/6calwv/what_do_you_actually_want_from_your_echo/">gripes</a> are: an inability to push notifications to the user (pretty much a necessity for social apps), no coordination between multiple Alexa devices (e.g. keep my music in sync on all devices as I walk through my house), inability to identify voice, and no raw recording.  
</p>

<p>
Lastly, <a href="https://www.reddit.com/r/amazonecho/comments/6dafr6/for_the_love_of_god_when_i_ask_you_to_play/">not all users</a> are impressed with the overall experience.  Relative to Siri or Google Assistant, the conversations can seem more robotic and less natural.  Users have to phrase things the way Alexa expects, not necessarily how they would typically speak.  For example, whereas I might naturally want to say "Alexa, order me a pizza from Pizza Hut", Alexa wants me to say "Alexa, tell Pizza Hut to order me a pizza".  Maybe not a big deal in the long run (as we adjust), but in my experience I do find myself having to think hard for the right words to speak - "hmmm, what the hell is that skill I enabled to find my phone again?  Is it 'Phone Finder'...or 'Find Phone'...or 'Find My Phone'?  Fuck it.  I'll just look under the couch cushions again."
</p>

<h3>What to Build?  What's the "Killer App"?</h3>
<p>
I'm certainly not a Gartner analyst or an oracle of consumer behavior, so to me it seems that the future is anything but clear.  Yes, the potential of the Alexa platform seems huge, but there are definitely some glaring red flags as well.  Assuming, however, that you're undaunted by these challenges and want to push forward and test your hand at publishing an Alexa skill, the question (of course) is, what should you build?  What is the best use of this technology?  Is there a "killer app"?  And if so, what is it?
</p>

<p>
Given the ubiquity of smart devices in general, the crux to me seems to be in thinking about the personal trade-off we all make as users in our every day lives.  When are we willing (or compelled) to give up the power and richness of our smart phone or desktop GUIs in favor of the austerity and simplicity of voice?  Amazon is making the bet that voice is always simpler, but I'm not so sure.  When I'm lounging on the couch, for example, would I rather ask Alexa to play that new album (that I can't exactly remember the name of), or just pick up my  phone that's sitting 1 foot away from me on the coffee table (if not in my hand!) and make a few taps?  In 2017, as humans have essentially reached a singularity with their smart phones, tapping seems almost easier and less conscious than speech (as scary as that sounds).  
</p>

<p> 
My sense is that we need to think about situations in which using our screen-based smart devices is just not possible.  This seems to be the premise of a great skill by <a href="https://www.amazon.com/Amazon-Allrecipes/dp/B01N3MS7AV">AllRecipes</a> - i.e. when you're in the kitchen, you're hands are dirty, and so it's better to speak than tap.  Another great hands-free zone is of course the car, and it appears that Amazon is <a href="http://www.techradar.com/news/you-can-now-get-amazons-alexa-in-your-car">working on it</a>.
</p>

<p>
There are also huge (and obvious) wins for the visually impaired, and companies can use Alexa to create an omni-channel experience to tap into this, albeit smaller, market. For someone with low vision, the Alexa skill might be the best (or only) option to order an Uber, even if the majority of people would still prefer to do it via their smart phone. 
</p>

<p>
Lastly, I wonder if the consumer-facing applications of Alexa are being overshadowed by the potential for business applications.  There have long been <a href="http://www.vocollectvoice.com/">companies</a> that have offered voice-driven functionality to employees (e.g. factory workers, warehouse pickers, health care workers, etc.), and I would think that Alexa's open platform could open up this market more.
</p>

<p>
In the end, my projections and pontifications might be obvious or off-base, but I do find the Alexa platform to be exciting.  I'd like to hear your thoughts though.  As a developer, what do you think about the Alexa platform?  Is it worth your while to jump in and learn about building applications with Alexa?  Or have you already?  What do you think will be the most useful skills?
</p>

				]]>			</description>
			<pubDate>Tue, 30 May 2017 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2017/alexa-killer-app-a-developers-view.php</guid>
		</item>
		<item>
			<title>Reflections of an "Old" Programmer</title>
			<link>http://www.bennorthrop.com/Essays/2016/reflections-of-an-old-programmer.php</link>
			<description>
				<![CDATA[				<section id="setup-blurb">
Note: I was invited to speak on the <a href="https://softwareengineeringdaily.com/">Software Engineering Daily</a> podcast on this topic, and it was a ton of fun.  Check it out <a href="https://softwareengineeringdaily.com/2016/11/09/reflections-of-an-old-programmer-with-ben-northrup/">here</a>.
</section>


<img src="http://www.bennorthrop.com/Essays/2016/old-programmer.jpg" align="right" width="250" />

<p>
I'm a programmer, a few months shy of his 40th birthday.  It's Saturday morning, my kids are home with my wonderful wife (who is pulling my weight on the domestic front), and I'm at a tech conference.  It's a session on <a href="https://facebook.github.io/react-native/">React Native</a>, and the presenter is convincing us why it's truly the "next big thing" for mobile development.  To me, it seems a bit like <a href="https://en.wikipedia.org/wiki/JavaServer_Pages">JSPs</a> of 15 years ago, with all the logic in the presentation code, but I'm "old", so I assume I just don't "get it".  
</p>

<p>The presenter blows through some slides, dazzles us with some impressive live coding, and then makes his way to the "name dropping" portion of the presentation, where he rattles off about a half a dozen supporting tools that I never knew existed, including something called <a href="https://github.com/futurice/pepperoni-app-kit">Pepperoni</a> (seriously).  As someone who just recently got the hang of <a href="https://angularjs.org/">Angular</a>, it all makes me feel a little disheartened.   "Here we go again", I think.
</p>

<p>
Of course I'm not really surprised.  Over the past 20 years, I've taken seats on a number of <a href="http://www.bennorthrop.com/Essays/2015/slaves-to-fashion.php">band wagons</a>, and have generally enjoyed the rides.  The buzz that comes with a new "disruption" in programming can be exciting - feeling apart of a community of technical innovaters, championing something that will make things a little easier, quicker, cleaner, better.  It can be fun.  But on this particular morning, at the cusp of 40, I have to admit I feel a little drained.  I know this is part of the job - if I want to stay relevant (and well paid), I know that every so often I need to cast out some of the knowledge that I've so dutifully absorbed, and gear up up for the next journey. It's just how it is.
</p> 

<p>
As I think about it though, this regular ritual of my programming career doesn't seem to be a way of life for other professionals.  The doctor at 40 doesn't seem to be worried about discovering that all his knowledge of the vascular system is about to evaporate in favor of some new organizing theory.  The same goes for the lawyer, the plumber, the accountant, or the english teacher.  While there are certainly unappealing aspects to these professions, it's safe to say that for each of them, mid-way through their career, the knowledge they've accumulated is relatively stable, and has afforded them with some increased measure of respect and compensation.  In programming though, <a href="http://www.infoworld.com/article/2617093/it-careers/it-careers-where-do-all-the-old-programmers-go.html">20 years of experience</a> does not seem to confer those same advantages.
</p>

<h3>Two Main Forces</h3>
<p>
Of course not all is so dismal in our profession - there are so many <a href="http://www.huffingtonpost.com/gretchen-rubin/balanced-life----why-is-c_b_904388.html">things to love</a> about being a programmer - but in terms of the never-ending struggle to "keep up", it is an interesting feature that seems more or less unique to our field.  Am I right though?  Is programming really different in this regard?  And if it is, then why?  And what does it mean for our career trajectory?  I'd like to try to answer <i>all</i> of this (because, why not) in terms of two concepts.
</p>

<p>
The first is <b>knowledge decay</b>.  Everything we know, not just about programming, has an expiration; a point at which it is no longer useful.  I learned how to drive a car when I was 16, and for that most part, that knowledge still serves me well.  This piece of knowledge could be said to have a long <a href="http://www.aacrao.org/resources/resources-detail-view/knowledge-decay--the-half-life-of-your-education">half-life</a>.  For many professionals, their domain knowledge also has a relatively long half-life.  Sure, new discoveries in medicine may displace some existing procedures, but likely there will not be a major overhaul in our understanding of our biology.  When the expiration is long like this, knowledge can effectively be considered cumulative.  The doctor is <i>more</i> knowledgeable than he was last year, because everything he learned in the past 12 months built on all that he knew before.  
</p>

<p>
In programming, for good or bad, I'd assert that this is not exactly the case.  Putting a (rather arbitrary) stake in the ground, I'd say that:
</p>

<p class="indentableSubtle">
Half of what a programmer knows will be useless in 10 years.
</p>

<p>
This could be way off (and there are many caveats of course - read on!)...but it seems about right for me.  If I learned nothing else from this point forward, I bet that only about a half of my knowledge could I still use in 2026 (long live SQL!), and the other half would probably be of no use (React Native, perhaps?).  Now of course I <i>will</i> be gaining new knowledge to replace the dead stuff, but will it be enough?  Will I know more (useful) knowledge in 2026 than I do now?
</p>

<p>
This brings me to the second concept, <b>knowledge accumulation rate</b> - the pace at which we add new things to our knowledge corpus.  In every field, there is a certain threshold of knowledge that must be met in order to be "certified" (or at least hireable), and the early portion of a career is typically dedicated to acquiring this knowledge.  In programming, however, because of the fast decay of knowledge, it seems like we never really transcend the "student" period.  We know we must <a href="https://tommcfarlin.com/always-be-learning/">always be learning</a>, and this makes the stages of our career a bit atypical.  


<h3>The Three Stages</h3>
<p>
If I were to graph an average programmer's knowledge over the course of their career, keeping in mind knowledge decay and accumulation rate, I think it might look like something this:
</p>
<div align="center">
<img src="http://www.bennorthrop.com/Essays/2016/career-stages-programmer.png" width="600" align="center" />
</div>

<p>
In the beginning of our careers, in what we could call the <b>eager apprentice</b> stage, accumulating knowledge is relatively easy.  Everything is new, and so each experience is a vehicle to gain more knowledge.  Moreover, since we're younger, we often have fewer hard obligations, and so we probably don't mind spending a few nights and weekends picking up new languages and frameworks.  Lastly, and importantly, the expectations on us from our employers is lower.  Everyone understands that we're junior, and so more easily than our colleagues, we can carve out a little time during the work day to fill in holes in our knowledge.  This is a fun stage, but there's this persistent feeling that there's so much we don't know.
</p>

<p>
At some point though we cease to be novices, and we establish ourselves as productive, self-sufficient developers.  For the first time, the gap between us and our colleagues (even the ones 10 years our senior!) does not seem so large.  This fills us with vim and vigor, and so this is the <b>rising star</b> stage.  The investment we made in learning has paid off, and just about everything we know is still useful - i.e. none of our knowledge has noticeably decayed.  With this reservoir full of relevant knowledge, we begin to earn the respect of clients, peers, and managers, and with this respect comes titles, salary, and opportunities.  Though we don't necessarily see it at the time, this is also an important point of inflection.
</p>  

<p>
It's at this point that two things happen.  First, that promotion to "senior" comes with something more than just money: greater expectations.  Employers need their star programmers to be leaders - to help junior developers, <a href="http://www.bennorthrop.com/Essays/2008/code_review_potluck.php">review code</a>, perform interviews, attend more meetings, and in many cases to help maintain the complex legacy software they helped build.  All of this is eminently reasonable, but it comes, subtly, at the expense of our knowledge accumulation rate.  The time we used to have to read tech blogs: gone.  Second, it's also at this point that we first experience (or at least recognize) a little knowledge decay.  Some of what we learned early in our career is now out-dated.  All that time "we" (read: I) spent learning <a href="http://www.gwtproject.org/overview.html">GWT</a>?  Lost!  Essentially, both forces, knowledge decay and knowledge accumulation rate, begin to work against us.
</p>

<p>
It's at this point where we enter the third and final stage, the ebb-and-flow of the <b>steady veteran</b>.  We are knowledgeable and productive, yes, but we also understand that we may actually know fewer (useful) things than we did at a prior point in our career.  A non-trivial amount of our knowledge has decayed, and we may not have had the time to accumulate enough new knowledge to compensate.  This can be frustrating, and I think it's why it's at this point that so many of us bail for other pastures - management, sales, testing, or (my dream) <a href="http://hello-world.io/death-of-a-programmer-life-of-a-farmer/">farming</a>.  We realize that it'll require real effort to just maintain our level proficiency - and without that effort, we could be <i>worse</i> at our jobs in 5 years than we are today.  There is no coasting.
</p>


<h3>Humble Advice</h3>
<p>
This is where I'm at.  I still love to learn, but I appreciate that without some herculean effort, I will probably always remain in an equilibrium state hovering around the lower boundary of "expert".  I'm ok with this, because I enjoy my personal life more than I want to be the next <a href="http://martinfowler.com/">Martin Fowler</a> (although I bet Martin has a kick-ass personal life too - that guy is amazing).  Thinking about my career in terms of knowledge decay and accumulation though has changed my perspective a little.
</p>
<p>
First, I try to <b>take the long view</b>.  I'm more wary of roles with excessively taxing expectations and few opportunities for novel experiences.  I've seen quite a few colleagues take the bigger pay check at an employer where there'll be little opportunity to work with new things and learn.  In 5 years, they realize that much of their valuable knowledge has evaporated and their pay is way out of whack with their <i>actual</i> worth.  In some cases, I think making less money in the short term (at a better employer) will yield more money (and stability) over the course of a long career.
</p>

<p>
Second, given that time is limited, I try to <b>invest most in knowledge that is durable</b>.  My energy is better spent accumulating knowledge that has a longer half-life - algorithms, application security, performance optimization, and architecture.  Carving out niches in these areas, I hope, will better bullet-proof my career than learning the newest, flash-in-the-pan Javascript library.  
</p>

<p>
In the end, perhaps I haven't really forged any new ground here, but it's been useful for me to think about my career in terms of these two things: knowledge decay and knowledge accumulation.  I'd love to hear any thoughts you have!
</p>

<h3>Other Posts</h3>
<ul>
<li><a href="http://www.bennorthrop.com/Essays/2013/developer-motivation.php"> The 3 Motivational Forces of Developers</a></li>
<li><a href="http://www.bennorthrop.com/Essays/2012/the-user-interface-and-the-halo-effect.php">The User Interface and the Halo Effect</a></li>
<li><a href="http://www.bennorthrop.com/Essays/2013/pair-programming-my-personal-nightmare.php">Pair Programming - My Personal Nightmare</a></li>
</ul>				]]>			</description>
			<pubDate>Thu, 06 Oct 2016 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2016/reflections-of-an-old-programmer.php</guid>
		</item>
		<item>
			<title>The Agile Fantasy Draft</title>
			<link>http://www.bennorthrop.com/Essays/2016/agile-fantasy-draft.php</link>
			<description>
				<![CDATA[				<p>I'm not an Agile zealot, but I'm also not a complete hater (of which there seem to be <a href="https://www.google.com/url?q=https%3A%2F%2Fsoftwarebypaul.wordpress.com%2F2016%2F03%2F11%2Frun-away-from-agile%2F&sa=D&sntz=1&usg=AFQjCNFA9dN6XbqRfGXemfJnQq-U_d1pBA">many</a>, <a href="https://michaelochurch.wordpress.com/2015/06/06/why-agile-and-especially-scrum-are-terrible/">many</a> nowadays).  With that disclaimer out of the way, there's a part of Agile (specifically, Scrum), that I've always been fuzzy on.</p>

<p>The team goes through sprint planning, <a href="https://www.scrumalliance.org/community/articles/2011/march/how-to-hold-an-effective-backlog-grooming-session">grooms the work</a>, plays their little <a href="https://www.planningpoker.com/">poker games</a>, yada yada, and eventually gets to a set of work items that it endeavors to accomplish in the upcoming sprint.  Great.  Now what?  Specifically, <b>how do those work items get into the hands of individual developers</b>?  In other words, how does the work get assigned?</p>

<p>The simple solution is "central planning", and though this fundamentally contradicts the <a href="https://scrumalliance.org/community/articles/2013/january/self-organizing-teams-what-and-how">self-organization</a> edict of Agile, it is, in my experience, the model which many teams use.  The project manager/scrum master/tech lead has some intuition as to which developers would be best suited for which work, and goes about assigning stories/tasks based on that understanding.  The end goal here is expedience - rather than a long drawn out discussion, let one person make the judgement call on who is the optimal person to complete a given piece of work.</p>

<img class="image" src="http://www.bennorthrop.com/Essays/2016/draft-day-1.jpg" width="200" style="float: right;" />

<p>The problem, of course, is that while this may optimize what's good for the <i>project</i>, it doesn't necessarily satisfy the goals of the <i>individuals</i>.  A team may plod along with the "central" model for a few sprints, but it won't be long until some tension and resentment foments: "why does Jane get all the fun UI work?" or "I'm so f-ing sick of working with the accounting module", etc.  Basically, we developers all want <b>some degree of autonomy and self-direction</b>, and so we'd like some choice in what we work on.</p>

<p>And this of course is why one of the pillars of Agile <i>is</i> self-organization.  The problem is that there's no good, thoughtfully specified process for assigning work items, and so teams can instead end up adopting what amounts to a Hunger Games-style free-for-all.  Planning is over, the work is ready, the horn blows, and the team rushes to their laptops to grab the work they want.  This is probably an exaggeration - maybe instead there's a post-planning discussion where developers make dispassionate arguments as to why they should take the fun, new feature and someone else would be better off making a small enhancement to the registration form.  In any case, the same tension and resentment can build, but this time directed at each other rather than the lead.</p>

<p>A solution that we've stumbled on (and have now used on a few projects) is the <b>fantasy draft</b>.  At the risk of explaining the obvious, here's how it works:</p>

<ul>

  <li>Sprint planning happens.  Work for the sprint is identified, prioritized, and estimated (or not).<br/><br/></li>

  <li>Each person on the team picks a number out of a hat, bag, or container of preference.<br/><br/></li>

  <li>The team comes together for the draft.<br/><br/></li>

  <li>Starting with the first pick (duh), work items are chosen one-by-one until there is nothing left.</li>
</ul>

<p>There are subtle refinements to this process, of course.  We've instituted a clock (2 minutes per pick!), a looping scheme (2nd round goes in reverse from last pick to first), and a carry-over rule (work unfinished in a previous sprint is automatically carried over to the same developer).  We've also considered "franchise players" and allowed draft pick trades.</p>

<p>In general, it works pretty well, and, if nothing else, is a lot of fun.  Draft day comes with all the frivolity that you'd expect from a fantasy draft - someone wasted their first round pick on  a trivial user story, someone couldn't pick in time, etc.</p>

<img class="image" src="http://www.bennorthrop.com/Essays/2016/draft-day-2.jpg" width="200" style="float: left;" />


<p>Beyond the fun though, the draft system has some other nice qualities, most notably fairness.  People are <b>in control of their own destinies</b>.  If they get the shaft this sprint with a shitty draft pick, well, next sprint they'll likely do better.  It also distributes the "fun" work more equally.  If the UI is the most desirable tier to work in, with the draft system it's more likely that most people will get an opportunity to get their hands in there in some capacity.  This might come at the price of efficiency, but definitely aids maintainability and knowledge dispersion.  </p>

<p>There are, of course, some downsides.  The most obvious is that it gives no preference to seniority or capability.  That complex integration piece can be picked up by the a junior UI developer if he so chooses.  On the flip side, the most senior developer might get stuck writing the 93rd login form of their career (and be none too excited about it).  As a "senior"-type person, admittedly, this can suck.</p>

<p>Anyway, I write this less to advocate the fantasy draft as the model that you should use, but more as a way to find out what others do on their teams.  How is work assigned?  What are the pros and cons?</p>

<p><i>Thanks to <a href="https://www.facebook.com/handersongomesphotography/">Handerson Gomes</a> for the pictures!</i></p>				]]>			</description>
			<pubDate>Tue, 07 Jun 2016 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2016/agile-fantasy-draft.php</guid>
		</item>
		<item>
			<title>If you Speak Up, Speak First!</title>
			<link>http://www.bennorthrop.com/Essays/2016/if-you-speak-up-speak-first.php</link>
			<description>
				<![CDATA[				<p>As a developer, there are often situations in which the team discusses big decisions and where there are opinions on each side.  Consider this scenario...
</p>

<p class="indentableSubtle">The team is re-architecting a core service, and is considering whether to go with design A or design B.  Both have pros and cons (in terms of scalability, performance, etc.) and the team is uncertain which route to go.  From prior experience, you have solid reasons to prefer design B, but as the new guy on the team, you decide to let the conversation play out before you chip in your 2 cents.</p>

<p>Fail!  Wait...already?  Yes.  What many people don't realize is that <b>early opinions matter incommensurately</b>, and if you feel strongly about a given decision, you need to chime in first.  The reason for this is called a <a href="https://en.wikipedia.org/wiki/Information_cascade">cascade</a>.  To see how it works, consider again your team, and their individual preferences <i>before</i> discussion:</p>

<table style="font-size: 11pt; background-color: #F2E6B6" width="400" align="center" border="1" class="simpleTable">
  <tr>
    <td></td>
    <td width="10%"><b>You</b></td>
    <td width="10%"><b>Dana</b></td>
    <td width="10%"><b>Al</b></td>
    <td width="10%"><b>Fran</b></td>
    <td width="10%"><b>Bob</b></td>
    <td width="10%"><b>Carlo</b></td>
  </tr>
  <tr>
    <td>Preference (pre)</td>
    <td>B</td>
    <td>B</td>
    <td>A</td>
    <td>B</td>
    <td>A</td>
    <td>B</td>
  </tr>
</table>    
<br/>
<p>
As you can see, before discussion, there's a 4-2 split among the team in favor of the design you prefer, design B.  All things being equal then, you would expect the team to arrive at a consensus for this design, but in reality, this consensus is anything but assured - <b>it depends highly on how the discussion plays out</b>.  Imagine the team goes around the room and one-by-one states their preference and then explains their reasons.  Al and Bob are always the most out-spoken, so they go first:</p>

<table  style="font-size: 11pt; background-color: #F2E6B6" width="240" align="center" border="1" class="simpleTable">
  <tr>
    <td></td>
    <td width="40"><b>Al</b></td>
    <td width="40"><b>Bob</b></td>
  </tr>
  <tr>
    <td>Preference (pre)</td>
    <td>A</td>
    <td>A</td>
  </tr>
  <tr>
    <td>Stated Preference</td>
    <td>A</td>
    <td>A</td>
  </tr>
</table>    
<br/>

<p>
Both Al and Bob, who also happen to be the most senior developers, go on the record supporting design A and then give their reasons (which are sensible, by the way).  Now, it's Carlo's turn.  His preference is for option B, but he also is new to the team, so he begins to reconsider.  Despite the fact that Carlo has a good reason for option B, he wonders, "is it worth it to go against the grain here"?   Not confident in his own opinion and fearing a little blow-back from Al and Bob, Carlo decides its safer to just go along with the consensus opinion and <i>states</i> a preference for option A.  And here starts the cascade!</p>

<table  style="font-size: 11pt; background-color: #F2E6B6" width="400" align="center" border="1" class="simpleTable">
  <tr>
    <td></td>
    <td width="10%"><b>Al</b></td>
    <td width="10%"><b>Bob</b></td>
    <td width="10%"><b>Carlo</b></td>
    <td width="10%"><b>Dana</b></td>
    <td width="10%"><b>Fran</b></td>
    <td width="10%"><b>You</b></td>
  </tr>
  <tr>
    <td>Preference (pre)</td>
    <td>A</td>
    <td>A</td>
    <td>B</td>
    <td>B</td>
    <td>B</td>
    <td>B</td>
  </tr>
  <tr>
    <td>Preference (stated)</td>
    <td>A</td>
    <td>A</td>
    <td>A</td>
    <td>A</td>
    <td>A</td>
    <td>A</td>
  </tr>
</table>    
<br/>

<p>
It's important to note that not only did Carlo switch his preference to option A, but he also withheld a valuable bit of knowledge that only he had in favor of option B - knowledge that could have been persuasive to others.  In any case, by the time it gets to Dana, Fran, and you, it seems as though the proverbial ship has sailed.   There is solid support for option A, and there's not much sense in talking it out further.  </p>
  
<p>
But wait...didn't the team, collectively, prefer option B?  What happened here?  Why did the <i>group</i> decision succumb to the preference of the few who spoke first?  This is the power of the cascade - people go along with the observed actions of others, even when these actions contradict their own private beliefs. This can happen for a couple of reasons.</p>

<p>
First, <b>people naturally like to agree with each other</b>.  This is so much the case that when we do, we actually both end up <a href="http://www.sciencedirect.com/science/article/pii/S002210310300091X">feeling better about ourselves</a> ("Oh, you like React?  I like React!  We both must be exceptionally brilliant people!").  When we happen to disagree, depending on the social context, there can be a cost - others might actually think worse of us for our dissenting opinions.  This is real, although it depends highly on the team environment and on the group leaders (we all know tech leads who are more or less accepting of divergent opinions).  When people defer to the preference of a person with more seniority, against their own preference, this is called a <a href="http://truthonthemarket.com/2009/12/10/informational-cascades-reputational-cascades-group-polarization-and-the-climate-emails/">reputational cascade</a>, and it happens often.</p>

<p>
Second, as people consider the preferences of others, they begin to <b>discount their own reasons</b> for favoring or opposing a given decision.  This is called an <a href="https://en.wikipedia.org/wiki/Information_cascade">informational cascade</a>.  "Wow, 100 people liked this song?  Maybe I'm wrong, it probably is good!".  As the cascade rolls over people, it gets ever stronger, as people withhold not only their original preferences but also information that they uniquely held that would be relevant to others in making the decision.  This happens in plenty of real-world instances (for example, <a href="http://blogs.cornell.edu/info2040/2012/11/13/information-cascades-in-juries/">juries</a>), and to sometimes alarming effect.</p>

<p>
The moral here is probably not exactly what the title suggests, although it is true - speaking first will likely give you more persuasive power.  More constructively though, we should try to structure our team discussions with an awareness of cascades.  Get all the information on the table before allowing people to state their preferences.  And if junior people are worried about going against the grain, let them speak first, or just have everyone write down their preferences on a piece of paper, and tally the anonymous votes.  I've done this often, and it can make a boring decision fun(ish).</p>

<p>
Anyway, I'd be curious to hear what you have to say.  Does this happen on your teams?  Do the outspoken people on your team have inordinate sway over team decisions? </p>				]]>			</description>
			<pubDate>Wed, 02 Mar 2016 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2016/if-you-speak-up-speak-first.php</guid>
		</item>
		<item>
			<title>Let's not be Slaves to Fashion</title>
			<link>http://www.bennorthrop.com/Essays/2015/slaves-to-fashion.php</link>
			<description>
				<![CDATA[				<p>For as long as I've been in the industry, it's always been this way. You talk to a fellow programmer, and inevitably the conversation veers toward the same, perfunctory exchange:</p>

<p class="indentable">  "So...what are you using?"</p>

<p>...at which point you respond with the newest, flashiest piece from your current stack:</p>

<p class="indentable">  "Ohhh...it's just basic Java/Spring on the back-end, but on the UI it's Angular (!)"</p>

<p>The purpose of the exchange is of course not to objectively describe a set of technologies used to solve a problem. Instead, we highlight the "cool" language/tool/framework in order to <b>reveal something about our ourselves</b>, our identity. We're not just average programmers. We use Angular (or whatever). We're in the "in crowd".  In a sense, the technologies we use are like the clothes we wear - they speak to who we are, what we stand for, our worth. It's technology as fashion. </p>

<p>Now of course the analogy is far from perfect, but consider some parallels from this description of the <a href="http://onlinelibrary.wiley.com/doi/10.1111/j.1533-8525.1969.tb01292.x/pdf">fashion cycle</a> by sociologist <a href="http://en.wikipedia.org/wiki/Herbert_Blumer">Herbert Blumer</a>:</p>

<p class="indentableSubtle">  The elite class seeks to set itself apart by observable marks or insignia, such as distinctive forms of dress. However, members of the immediately subjacent classes adopt these insignia as a means of satisfying their striving to identify with a superior status. 
<br/>
<br/>
  They, in turn, are copied by members of classes beneath them. In this way, the distinguishing insignia of the elite class filter down through the class pyramid. In this process, however, the elite class loses these marks of separate identity. It is led, accordingly, to devise new distinguishing insignia which, again, are copied by the classes below, thus repeating the cycle.</p>

<p>In a nutshell, fashion, whether in clothing, music, or programming, is about class differentiation.  The elites innovate. The masses catch up so they can be associated with the elites.  As soon as they do, however, the elites are no longer "elite", and so they must break away and innovate again. The masses eventually follow, and the cycle continues, ad inifinitum.</p>

<p>Obviously, there's more to it in the case programming - our choice in technologies can't be as whimsical as our choice in hair style.  Our decisions must be grounded in a strong base of pragmatism - i.e. what we use should actually <i>work</i>. Still though, I think we understand that there's always been a degree of fashion in our industry.  Whether it's Angular today, or GWT, Rails, or JSPs of yesteryear, there's always been that "next best thing" and we've always scrambled to keep up.  </p>

<p>Now, sure, we often jump the bandwagon out of earnest hope that we've finally found the <a href="http://worrydream.com/refs/Brooks-NoSilverBullet.pdf">silver bullet</a>, or some close approximation.  I think just as often, however, we jump on the bandwagon so that we can sit alongside the "cool kids" and not be "left behind".  Ok, we could have used a technology we know and are proficient with, but that technology is old and lame now.  We use what's new.  We're up on things. We're "current".  </p>

<p>To be clear, it's not the innovation itself that is dangerous, but rather the <b>vacuous emulation</b> of it.  When we use a tool, a framework, or a language <i>only</i> because it's new or "hot", we are taking on non-trivial amounts of risk to our projects and our clients.  We make our systems less maintainable and unnecessarily complex.  Even when the new technology is by all standards "better", we should be sure that it is better for our project and organization and solves the particular problems that we need to solve. </p>

<p>Unfortunately though, I feel like this empty, reckless adoption of new technologies is more prevalent than ever.  For example, I hear this kind of exchange alarmingly often lately - a programmer unabashedly suggesting technologies to another without even understanding the context:</p>

<p class="indentable">  "You know, you really should have used MongoDB"</p>

<p>Really? We only had 1MB of data and the rest of the organization was using MySQL. More importantly, we finished the project in scope, on time, and on budget!</p>

<p>Again, I'm not at all bemoaning the process or cycle of innovation itself.  Innovation is our business.  We create.  We make things better.  This is great.  I do think, however, that the ever increasing pace of innovation, on all fronts (e.g.NoSQL databases, Javascript frameworks, Mobile toolkits, etc.), is playing into our hard-wired psychlogical desire to "keep up", and to ill effect.  I know myself that I'm often so overwhelmed by how much new "stuff" there is out there, and moreover by the paucity of free time I have to reasonably evaluate it, that I often catch myself reverting to fashion-based decisions.  That guy at the conference told me that <a href="https://code.google.com/p/go/">Go</a> was the next big programming language - I better start using it!</p>

<p>So as I get off my soap box, let me make one last plea. If you're in the elite, keep the innovation coming (obviously). Those in the masses, however, let's not be afraid to let a bandwagon or two pass us by. Let's be <b>judicious about adopting innovation</b>. The right tool for the right problem. In other words, let's not be slaves to fashion.</p>

<p>As always, let me know what you think!</p>
				]]>			</description>
			<pubDate>Tue, 06 Jan 2015 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2015/slaves-to-fashion.php</guid>
		</item>
		<item>
			<title>The Siren Song of Automated UI Testing</title>
			<link>http://www.bennorthrop.com/Essays/2014/the-siren-song-of-automated-testing.php</link>
			<description>
				<![CDATA[				<p>
For more than a decade now, cautionary tales have been written about the <a href="http://www.uml.org.cn/test/pdf/automate.pdf">costs</a>, <a href="http://www.satisfice.com/articles/test_automation_snake_oil.pdf">perils</a>, and <a href="http://blogs.msdn.com/b/steverowe/archive/2008/02/26/when-to-test-manually-and-when-to-automate.aspx?Redirected=true">complexities</a> of automating UI tests, and yet we, on the business and development sides, still seek the promise land (as depicted by the graph below).  
It often starts with a familiar story... 
</p>

            <center><img src="http://www.bennorthrop.com/Essays/2014/automated-testing-roi-perceived.gif" width="350"/></center>
<br/>

<p>
The application is launched, and it's a big success.  Users are happy.  Unfortunately, there's little time to celebrate, because with success comes requests for new features and enhancements.  And they're coming in fast.  Fortunately, the development team is up for the challenge.  They start churning out code, and the team does frequent releases to keep pace with the feature demand.  
</p>

<p>
Things are going well for a while, but as the application grows, things get a little more complicated.  The team finds that even with solid automated <a href="http://www.bennorthrop.com/Home/Blog/unit_testing_daos_and_database_code.php">unit testing</a> practices in place some new features end up breaking old features in quite unexpected ways.  Regression bugs.  Ugh.  Users get frustrated, and so business owners do too.  
</p>

<p>
To avoid these embarrassing snafus, the team decides to slow down, and implement a more rigorous <a href="http://en.wikipedia.org/wiki/Regression_testing">regression testing</a> practice.  The problem is, this being the nascent stages of the application, regression testing is all manual, and as everyone knows manual testing is <a href="http://programmers.stackexchange.com/questions/186690/relative-value-of-manual-vs-automated-testing">time consuming</a>.  Exorbitantly so.  
</p>

<p>
After just a few releases of comprehensive manual regression tests, it becomes obvious that this is a big bottleneck.  The business demands frequent releases, but there just isn't the QA capacity to keep up.  The team has two choices.  They can choose to slim down its testing scope so that regression tests can be completed more quickly, but of course this would introduce a greater likelihood of regression bugs.  Alternatively, the team could choose to release less frequently so not to repeatedly incur the high cost of regression testing, but then users would have to wait longer for new features, and time-to-market opportunities would be missed.  Neither choice is pleasant, and the business grows concerned.
</p>

<p>
It's here that someone introduces the idea of automating the UI regression tests.  Eureka!  By automating tests, the team can have it's cake and eat it too.  The scope of the regression tests needn't be narrowed, since automated tests can execute faster than a human.  Also, releases can be frequent, because automated tests can be run as often as needed.   The graph above captures the promise of automated UI testing.
</p>

<p>
Note that the cost function for manual testing is linear - it costs a fixed X for each run of the test.  The cost of automated testing on the other hand is a step-wise function: to run it once costs more than running it manually (because you have to write the test), but then every subsequent run costs nothing at all.  Overall return on investment is achieved when the two lines intersect, and so the more often you run the tests, the more you save.    
</p>

<p>
This is the promise at least, and both sides (for once!) are completely on board.  The business owners love the idea - they can get features to market more quickly and with high quality, and still not have to hire a larger QA staff.  The developeres love the idea as well - automation is basically a <a href="http://www.amazon.com/Pragmatic-Project-Automation-Deploy-Monitor/dp/0974514039/ref=sr_1_3?ie=UTF8&qid=1392763582&sr=8-3&keywords=automation+pragmatic+programmer">virtue<a> of every good programmer, and it's always exciting to play with the cool testing framework du jour to boot.  A win-win!
</p>

<p>
Sadly, as anyone who has experience with automated UI testing knows, it never quite works out this way.  While some organizations do eventually achieve some ROI automating UI tests, quite often the effort is a fruitless boondoggle - the tests that result are either unmaintainable, ineffective, brittle, or all of the above.  Time and money are sunk, and little value is really extracted.  The problem, in my opinion, is not that automated UI testing is hopeless, but rather that the expectation that is set up front about automated testing's ROI, as captured in the graph above, is overly simplistic.  In my experience, effective automation is more expensive to implement up-front, and still requires non-trivial "care and feeding" throughout its life.  In other words, automated UI testing is <a href="https://www.templateroller.com/template/2146798/no-silver-bullet-essence-and-accident-in-software-engineering-frederick-p-brooks.html">no silver bullet</a>.
</p>

<p>
In the rest of this post I'd like to explore some of the subtle or unexpected challenges in automated UI testing I've come across in my project experiences, and hopefully re-frame a better image of its expected ROI.  Ok, here we go...
</p>


<h3>Test resiliency vs. brittleness</h3>
<p>
The graph above belies probably the most important insight about automated tests: they're not all equal.  Tests can be written to be resilient, such that a failure of the test almost always indicates a failure of the feature.  These are tests you can trust.  Alternatively, they can be written to be brittle, such that trivial changes to the application or data cause the tests to fail.  These are tests to be wary of.  When they fail, they must be examined, re-run, and then either tweaked or re-written altogether (i.e. <a href="http://www.uml.org.cn/test/pdf/automate.pdf">test death</a>).  
</p>

<p>
In practice, tests can fail for all sorts of reasons.  The location or order of UI elements on the screen might change.  A brittle test would break, but a resilient test would account for this.  Data might be valid when the test was written, but may have changed when the test was run.  A brittle test would break, but a resilient test would set up fresh data and tear it down after.  There might be a network hiccup that causes the UI to be unresponsive.  A brittle test would break, but a resilient test would recognize this and try again.  And so on.
</p>

<p>
As expected, it takes much more time and skill to create a resilient test than a brittle one, but the resilient test will live longer.  Given this distinction then, it's clear that the cost function of automated tests should be bifurcated. The line below shows how brittle tests are relatively cheap to write, but will die quickly.  The line above shows how a resilient test is more expensive to write, but will last longer:
</p>

            <center><img src="http://www.bennorthrop.com/Essays/2014/automated-testing-roi-reality.gif" width="350"></center>
<br/>

<p>
It's important to note that this picture is actually generous for brittle tests.  In many cases they will die before they reach the point of intersection with manual testing (i.e. no ROI).  The canonical example of a brittle test is a <a href="http://testobsessed.com/2010/07/random-thoughts-on-record-and-playback/">record-and-play</a> script created, say, with a simple <a href="http://docs.seleniumhq.org/projects/ide/">Selenium plugin</a> with almost zero effort.  For a variety of reasons (like the ones given above: UI order, data, network), this type of test will probably die before the week ends.  
</p>
  
<h3>Strong vs. weak verification</h3>
<p>
Another important distinction to draw of tests is their verification effectiveness.  Tests can be written to be extremely observant, or completely clueless.  For example, it's not uncommon that a suite of automated UI tests might run, pass with 100% success, and then later that day a business owner will notice that all the text is lime green and the content areas are in random places.  The application is obviously broken, and any human tester would notice it in a single glance, but the automated test was never written to verify the look-and-feel of the application.  Given that the <a href="http://www.uml.org.cn/test/pdf/automate.pdf">entire point</a> of a test is to catch defects, this test failed its mission.
</p>

<p>
The point here is that tests can be written with weak or strong verification abilities.  On one end of the spectrum, the test could wander through the application and just verify that there were no errors.  This would be cheap to implement, but it might not give much confidence that the application is truly working.  On the other end of the spectrum, the test could try to mimic a human tester's judgement, verifying anything and everything a human would look for.  This, unfortunately, is not easy (if even possible).  There is a choice to be made, therefore, about the type of tests that should be created, and the more effective a test is at spotting defects, the more costly that test will be to write.
</p>


<h3>Maintenance is never free</h3>
<p>
Even if you choose to write resilient tests, maintenance of them is still not free (as the horizontal line in the first graph suggests).  Someone must monitor test runs, and when a test fails, that person must investigate.  Resilient tests should only fail for valid reasons, but a human still needs to make sure.  In these cases, the maintainer will most likely first try to re-create the test failure, either by re-running the test and watching it, or stepping through it manually.  If it breaks again, great, a defect report can be written up.  If not (as often happens), the maintainer needs to dig in and figure out why it would break once but not again.  What do the application logs say at the time the test broke?  What else was happening at that time?  What did the data look like?  There are plenty of variables, and it often takes a non-trivial amount of time to understand what happened.  In a nutshell, maintaining automated tests is not free.
</p>

<h3>The automation infrastructure</h3>
<p>
Beyond examining test failures, someone also must be responsible for kicking them off, or better yet configuring them to run on some schedule (from a <a href="http://martinfowler.com/articles/continuousIntegration.html">continuous integration</a> server, say).  The more robust the setup, however, the more technical complexity that's taken on.  Managing this complexity can cost a non-trivial amount of time and effort.  Tests can suck resources from machines, causing headaches (e.g. memory errors, etc.) for administrators.  Tests can take a prohibitive amount of time to run and need to be <a href="https://code.google.com/p/selenium/wiki/Grid2">forked/clustered</a>.  Tests can hit security blocks (e.g. tests need to mimic user behavior, and users often need to log in, but how does the test login though without storing someone's actual password?).  Or finally, tests can depend on frameworks and libraries that must be upgraded.  The point is that automated tests introduce a slew of technical challenges never encountered in the world of manual testing.
</p>


<h3>Making the app testable</h3>
<p>
A final often-overlooked cost is the time it takes to make the application itself testable.  For an automated test to drive a screen, it must have some hook for the UI elements.  For example, in order to "Enter 'John Doe' in the 'name' field", the test needs some way to find the 'name' field.  Some approaches for locating UI Elements (e.g. using preceding label names, <a href="http://www.w3schools.com/xpath/">XPath</a>) can be brittle, since small, seemingly innocuous changes to the UI can still confuse the test, and cause it to not be able to find the UI elements it needs to drive.  When this happens, tests fail.  
</p>

<p>
Resilient methods for referencing UI elements can sometimes require changes to the application itself (e.g. adding an "id" attribute to input elements, if the application is HTML based).  In some instances, making these changes can require a significant effort.  Again, this is a challenge avoided when testing manually.
</p>

<h3>Conclusion</h3>
<p>
In this post I painted a gloomy picture of automated UI testing, probably too gloomy.  My experience has not been that automated UI testing is necessarily ineffective or a waste of time, but rather that the promise land of easy, cheap, human-quality testing via automation is a chimera.  I've seen many teams go down the path of automated testing with rosy expectations, only to emerge 6 months later with hundreds of man-hours burned, a set of brittle tests with weak verification abilities, and only a handful of successes (i.e. defects prevented).  In a future post, however, I'd like to correct this gloomy course and talk about situations in which automated UI testing can work, in my experience.  Until then, I'd love to hear any comments you had, good or bad.  Thanks!
</p>				]]>			</description>
			<pubDate>Wed, 19 Feb 2014 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2014/the-siren-song-of-automated-testing.php</guid>
		</item>
		<item>
			<title>Code like a Champion Today</title>
			<link>http://www.bennorthrop.com/Essays/2013/code-like-a-champion-today.php</link>
			<description>
				<![CDATA[				<p>
Ergonomics aside, does a kick-ass work space help us write better code?  Or conversely, does working in drab old cubeville sap us of our coding potential?  How much does our working environment shape our job performance?  Or would we write the same code where-ever we sit?  </p>

<p>
I've always been fascinated with how subtle, unexpected forces like this shape our behavior.  This is the world of <a href="http://en.wikipedia.org/wiki/Priming_(psychology)">pyschological priming</a>, and I think its advocates would proffer the answer is "yes", features in our environment probably do matter.  One of the <a href="http://www.yale.edu/acmelab/articles/bargh_chen_burrows_1996.pdf">more famous studies</a> of priming goes something like this:
</p>

<p class="indentableSubtle">
A participant is sent to a room where she reads a series of words.  <i>Clean, private, thirsty</i>.  She next walks down the hall to another room for the second part of the study.  Unbeknownst to her, however, walking down the hall <i>is</i> the study - in particular, what is being measured is exactly how fast she does it.  If she's primed with words that conform to an elderly stereotype, she'll walk slower than if primed with neutral words.  For example, <i>Florida, wrinkled, bingo</i>.  Reading those words subconsciously impels her to slow her gate.  
</p>

<p>
Now there's a bit of a <a href="http://www.psychologytoday.com/blog/cognition-without-borders/201310/social-priming-course-it-only-kind-works">brouhaha</a> over the reliability of some of these priming experiments, but there seems to be <a href="<a href="http://opinionator.blogs.nytimes.com/2013/10/31/psyching-us-out/">too much evidence</a> to discount the phenomenon altogether - there's something to it.  External stimuli do impact our behavior in ways that fly beneath our conscious radar.  
</p>

<p>
So it made me curious, are there <b>subtle signals lurking in my physical environment</b> that make me better or worse at my job?  Or, maybe, could I plant some that would help my fellow developers (and I)?  Riffing off of Notre Dame's <a href="http://en.wikipedia.org/wiki/Play_Like_a_Champion_Today">famous mantra</a>, I taped this up in our stairwell...
</p>
<center><img src="http://www.bennorthrop.com/Essays/2013/code-like-a-champion-today-small.png" align="center" border="1" width="300" /></center>
<br/>
<p>
As the football players do, we all religiously hit the sign as we walk in to our office.  And to my surprise, I found that the lines of code per developer after being exposed to the sign increased by 27%!  </p>

<p>Ok, I'm making this up.</p>

<p>
I'm sure it didn't have any discernible effect; it's just a singular token.  But what about an environment rife with positive encouragement.  Those cheesy <a href="http://en.wikipedia.org/wiki/Motivational_poster">motivational posters</a>, perhaps?  If I put one up that shouts "Courage" at me, do I unknowingly feel more confident about refactoring some tangled piece of legacy code?  Or if I read "Integrity", am I more thorough with my estimates?  (It's not that ridiculous, actually.  There was <a href="http://bjsm.bmj.com/content/34/2/144.extract">a study</a> that found that a motivational poster placed at the bottom of a staircase and escalator doubled the use of the stair case.)</p>

<p>A little more serious, I wonder if perhaps some of the value of displaying our project management artifacts, like a <a href="http://leansoftwareengineering.com/2007/10/27/kanban-bootstrap/">Kanban board</a>, in our common areas is that they serve as positive primes - as we attend to them, our subconscious quietly whispters "stay on task"..."keep moving"..."work".
</p>

<p>
Or what about just positive symbolism without words?  Bold colors.  Open space.  Live plants.  Would we associate any of these with energy (or whatever), and would these <b>positive associations then trickle into our work</b>?  Basically, is there a ROI in those flashy, inpsiring <a href="http://www.smashingmagazine.com/2007/12/10/monday-inspiration-creative-workplaces/">Google-style workspaces</a>?     
</p>

<p>
I'm <a href="http://www.nature.com/news/disputed-results-a-fresh-blow-for-social-psychology-1.12902">not entirely confident</a> of the power of priming effects, but I would not be surprised that the environment we work in, and in particular the signs, symbols, diagrams, or signals,  would have some subtle impact.  Recently I've tried to be aware of this - leaving diagrams, etc. around to keep me focused.  What do you think?  Do features like these in your environment matter?  Or would you write the same code anywhere you were?
</p>

				]]>			</description>
			<pubDate>Wed, 11 Dec 2013 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2013/code-like-a-champion-today.php</guid>
		</item>
		<item>
			<title>The 3 Motivational Forces of Developers</title>
			<link>http://www.bennorthrop.com/Essays/2013/developer-motivation.php</link>
			<description>
				<![CDATA[				<p><i>Developers are a self-reflective lot.  On any given day, <a href="http://www.reddit.com/r/programming">/r/programming</a> will boast a handful of new posts pontificating on "what makes a 'good' developer" or the "X types of programmers".  So I know the topic space is <a href="http://www.codinghorror.com/blog/2009/07/meta-is-murder.html">over-tread</a>...but I don't care.  As a virtual rite of passage of a developer-blogger, I feel duty bound to submit my own classification of developers.  Here goes...</i></p>

<p>After 15 years in industry, I've come to realize that the <b>most defining quality of a developer is his source of motivation</b>.  It undergirds all of his decisions and interactions.  It predicts what kind of code he'll write, what technologies he'll prefer, and even how he'll succeed on a given assignment.  And it's often quite easy to peg for any given developer after just a few days of working with him or her.  
</p>
<p>
There are three and only three sources of motivation (so say I!), and they can be visualized as a <a href="http://en.wikipedia.org/wiki/Radar_chart">radar chart</a>, like so:  
</p>

<center><img src="http://www.bennorthrop.com/Essays/2013/developer-motivation.png" align="center" width="350" /></center>
<br/>
<br/>
<p>
At each vertex is the motivational force, and right smack in the center is the absence of any motivation at all (i.e. "don't give a crap").  You know who I'm talking about.  Anyway, each developer has his or her own unique "shape", where the greater the area of his triangle, the more motivation.  For instance, here's how I'd draw me, plus or minus:
</p>

<center>
<img src="http://www.bennorthrop.com/Essays/2013/developer-motivation-me.png" align="center" width="350" />
</center>
<br/>
<br/>

<p>Although a developer might be driven in some portion by all motivators, there is always one force that is most dominant.  I'll explain each: </p>


<p class="indentable">
<b>Business Motivated</b>: Driven most by a desire to get things done for the customer, these developers are often the "favorites" of the business folks because they deliver functionality quickly without many questions.  Need a new feature at the last minute?  No problem.  These guys have a can-do attitude (even when a little push-back might benefit the integrity of the system's architecture).  In terms of code, they think more concretely, and aren't always the best at creating abstractions that support re-use or other non-functional goals.  They just want to get 'er done and see a functional product.  On every project, a few of these developers are crucial.  They get things done, and don't make waves.
</p>

<p class="indentable">
<b>Technology Motivated:</b> These developers love learning new things for its own sake.  They're always eager to find the newest framework, language, or methodology and will take every opportunity to try it out on their current project.  The library was just released last week and was written by 1 guy over a weekend?  Let's give it a shot!  These guys know all the trending technologies, and have probably dabbled with them over nights and weekends.  They love to try things out, and understand which tools work best.  On a greenfield project they thrive, but when the field turns "brown" and new code turns into legacy, they look for greener pastures, or possibly worse, look for ways to shoe-horn in technology even if it's to the detriment of the system.
</p>

<p class="indentable">
<b>Problem Motivated: </b> Hard problems excite these developers, independent of whether what technology is employed or even it adds value for the business.  It's all about the puzzle.  Coming up with an elegant, clever, or quality solution is the victory.  If it helps the business in the process, great (and often it does).  These developers are interested in new technology insofar as it presents better ways of solving problems, but not so much interested in dabbling just to know what's out there.  While their solutions are solid, sometimes the details slip.  
</p>
 
<p>
Now of course this isn't the "right" classification system, but I've found that it is useful to think about my fellow developers as one of these 3 (or actually 4) types - the get 'er done's, the technologists, the problem solvers, and the don't-give-a-craps.  An awareness of each of our differences is helpful.  I know that each will have certain strengths and weaknesses, and will contribute to the project in different ways, and in different parts of the life-cycle.  
</p>

<p>
For instance, when starting a new project, we look for the technologists to help inform us about what framework or library on the horizon could be most useful.  Or when the team gets stuck in the weeds of over-analysis, we rely on the get 'er done's to just dig in and start delivering working code.  And when a problem is particularly thorny and needs to be thought through, we look for the problem solvers to step back and find a way out of the swamp.
</p>

<p>
In other words, everyone contributes in a different way.  Understanding people's underlying sources of motivation can help you get the most out of your team.  It can also make you cognizant of keeping a team in balance - too many of any particular type is never healthy, and in fact can spell disaster for your project.  Whereas a team of all technologists or problem solvers might obsess about the infrastructure and never deliver value to the business, a team of all get 'er done's might more quickly create a <a href="http://laputan.org/mud/">big ball of mud</a>.  
</p>

<p>
Anyway, let me know what you think!  What type of developer are you?  And does it matter?
</p>

<h3>Recent Posts</h3>
<ol>
<li><a href="http://www.bennorthrop.com/Essays/2013/expectations-and-the-endowment-effect.php">Expectations and the Endowment Effect</a></li>
<li><a href="http://www.bennorthrop.com/Essays/2013/consistency-and-innovation-pick-one.php">Consistency and Innovation: Pick One</a></li>
<li><a href="http://www.bennorthrop.com/Essays/2013/pair-programming-my-personal-nightmare.php">Pair Programming - My Personal Nightmare</a></li>
</ol>				]]>			</description>
			<pubDate>Tue, 12 Nov 2013 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2013/developer-motivation.php</guid>
		</item>
		<item>
			<title>AI Challenge at the Summa Summit</title>
			<link>http://www.bennorthrop.com/Essays/2013/ai-challenge-prisoners-dilemma.php</link>
			<description>
				<![CDATA[				 <span id="hs_cos_wrapper_post_body" class="hs_cos_wrapper hs_cos_wrapper_meta_field hs_cos_wrapper_type_rich_text" style="" data-hs-cos-general-type="meta_field" data-hs-cos-type="rich_text"><p>At the <a href="http://www.summa-tech.com/blog/2010/10/12/summa-summit-2010/">Summa Summit</a> this year, we tried out a new, hands-on coding activity that we dubbed "Coding Spaces". The general idea was to allow our technical consultants to get down and dirty (geeky!) - dabble in some new technologies, collaborate and program with others, and maybe even build something cool. Topics included <a href="http://angularjs.org/">Angular</a>, <a href="http://www.scala-lang.org/">Scala</a>, <a href="http://clojure.org/">Clojure</a>, <a href="https://www.leapmotion.com/">LEAP Motion</a>, <a href="http://salesforce.com/">Salesforce</a>, and <a href="http://en.wikipedia.org/wiki/Common_Lisp">Common Lisp</a> to name a few. It was a ton of fun. I led one session, an AI Challenge, and this post is a recap of what our group did in case you're interested, or in case you'd like to try this challenge on your own (the <a href="https://github.com/throp/SurvivorPrisonersDilemma">source</a> is included).</p>
<!--more-->
<h3>The Challenge: Prisoners Dilemma Tournament</h3>
<p>The challenge we competed in was a Prisoners Dilemma tournament, with a twist of Survivor. A little background is probably in order! The <a href="http://en.wikipedia.org/wiki/Prisoner's_dilemma">Prisoners Dilemma</a> is a canonical game in <a href="http://en.wikipedia.org/wiki/Game_theory">game theory</a>, which is typically used to explain why people don't cooperate with each other, even when it seems like it's in their best interests to do so. The game gets its name from this story:</p>
<p class="customIndent">You and your buddy get arrested for a crime that you both committed. It's clear that the authorities want you to confess, so they split you up into separate interrogation rooms, and interrogate you individually. If you confess and your buddy doesn't, the cops will go easy on you, say 1 year in jail, but they'll throw the book at your buddy, say 4 years in jail. The reverse situation is true as well - if he confesses and you don't, he gets 1 year and you get 4. If you both confess, however, they go a little easier on both of you, say 3 years. If neither of you confess, they give you 2 years on some trumped up charge.</p>
<p>Of course you know it'd be better to both "stay mum", but when you look at the outcomes in the table below, it's clear that it's in your best interests to confess no matter what your buddy does in the other room. If he stays silent, you're better off confessing (1 year</p>
<p>Â </p>
<table class="customTable" border="0" width="500" align="center">
<tbody>
<tr>
<td>Â </td>
<td><strong>Player 2 Stays Silent</strong></td>
<td><strong>Player 2 Confesses</strong></td>
</tr>
<tr>
<td><strong>Player 1 Stays Silent</strong></td>
<td>2 years, 2 years</td>
<td>4 years, 1 year</td>
</tr>
<tr>
<td><strong>Player 1 Confesses</strong></td>
<td>1 year, 4 years</td>
<td>3 years, 3 years</td>
</tr>
</tbody>
</table>
<p>Â </p>
<p>In the 1980s, political scientist <a href="http://en.wikipedia.org/wiki/Robert_Axelrod">Robert Axelrod</a> organized a <a href="http://en.wikipedia.org/wiki/Prisoner's_dilemma#Strategy_for_the_iterated_prisoners.27_dilemma">tournament</a> where participants of different backgrounds (mathematics, psychology, economics, etc.) created programs to play an iterated prisoners dilemma (i.e. round robin, multiple games) against each other. To everyone's surprise, the algorithm that won was the simplest of all, a "tit-for-tat" program devised by mathematician <a href="http://en.wikipedia.org/wiki/Anatol_Rapoport">Anatole Rapaport</a>. This tournament is often cited as a defense of cooperation in the large. Even though in small groups or in isolated instances being "mean" (in game theory parlance, "defecting") is the better strategy, over time it's much better to be "nice" (i.e. "cooperate").</p>
<p>This is a obviously a blazingly fast tour of the Prisoners Dilemma game, and I'm sure I didn't do it justice. I had read about this tournament initially in a book called the <a href="http://www.amazon.com/The-Origins-Virtue-Instincts-Cooperation/dp/0140264450">Origin of Virtue</a>, and then in Axelrod's own <a href="http://www.amazon.com/The-Evolution-Cooperation-Revised-Edition/dp/0465005640">The Evolution of Cooperation</a> a while back, and had always been fascinated by it. Is it really the case that tit-for-tat wins out? How long does it take for being "nice" to pay off? What if you're the only "nice" person (program!) in a world of "meanies"?</p>
<p>Well, this is what we endeavored to find out in our Coding Spaces. We replicated the famous Axelrod tournament, and as you'll see, got some very interesting results!</p>
<h3>Game Setup</h3>
<p>I created a simple engine to pit different game playing agents against each other. All the participant needed to do was implement the following interface (in any JVM language - I used <a href="http://groovy.codehaus.org/">Groovy</a>). If you want to follow along, you can download the source from GitHub <a href="https://github.com/throp/SurvivorPrisonersDilemma">here</a>.</p>
<pre class="java:nocontrols">
<code data-language="java">  package com.summa.summit.spd

  public interface Player { 

     /** Called at the beginning of each round */
     void onNewRound(int numGames)

     /** Called when your about to play a new opponent */
     void onNewOpponent(String opponentId)

     // Choose to cooperate or defect against the other player
     Decision play()

     /** Called after play() is called, and tells what your opponent did */
     void onGamePlayed(Decision opponentsDecision)

     /** If playing survivor mode, at the end of the round vote one player off */
     String voteOffIsland()

     /** Return the name of your program */
     String getName()

  }
</code></pre>
<p>Note that the Decision returned by the play() method is just a simple enum with two values: Cooperate and Defect. To give an example of a simple player, a very naive, always-be-"nice" strategy could look like this (in Groovy):</p>
<pre class="java:nocontrols">
<code data-language="java">  package com.summa.summit.spd

  public class MrNiceGuy implements Player { 

    def opponents = [:]
    def currentOpponent = ""

    Decision play() {
      return Decision.Cooperate // always be nice!
    }

    String voteOffIsland() {
      return opponents.isEmpty() ? currentOpponent : opponents.max { it.value }.key
    }

    String getName() {
      return "Mr. Nice Guy"
    }

    void onGamePlayed(Decision opponentsDecision) {
      if(opponentsDecision == Decision.Defect) {
        opponents[currentOpponent]++ // vote off the meanest person
      }
    }

    void onNewOpponent(String opponentName) {
      currentOpponent = opponentName
      opponents << [(currentOpponent) : 0]
    }

    void onNewRound(int numGames) {
      currentOpponent = ""
      opponents = [:]
    }

  }
</code>
</pre>
<h3>Tournament</h3>
<p>Out of the box, the initial Prisoners Dilemma game has four built-in players...</p>
<table class="customTable" border="0" width="400" align="center">
<tbody>
<tr>
<td><strong>Player</strong></td>
<td><strong>Strategy</strong></td>
</tr>
<tr>
<td>Mr. Nice Guy</td>
<td>Always be nice</td>
</tr>
<tr>
<td>Joe Evil</td>
<td>Always be evil</td>
</tr>
<tr>
<td>Rupert Random</td>
<td>Randomly cooperate or defect</td>
</tr>
<tr>
<td>Bob Backstabber</td>
<td>Always cooperate, except once in a while defect</td>
</tr>
</tbody>
</table>
<p>Â </p>
<p>If you're so inclined, once you download the game engine from GitHub (<a href="https://github.com/throp/SurvivorPrisonersDilemma">here</a>), you could play just these guys against each other by running the following from the root directory:<br> <code class="customCode"><br> > java -cp ./dist/groovy.jar;./spd.jar com.summa.summit.spd.SurvivorPrisonersDilemma<br> </code><br> This should give you a main menu, like the following:<br> <code class="customCode"><br> MAIN MENU<br> -----------------------------<br> 1) View players<br> 2) Add players<br> 3) Remove player<br> 4) Set # games per round (current = 10)<br> 5) Set survivor mode (current = false)<br> 6) Play!<br> 7) Exit<br> </code><br> Ok, back to the recap. On top of the default players, we had 7 "real" participants. Their strategies were, roughly:</p>
<table class="customTable" border="0" align="center">
<tbody>
<tr>
<td><strong>Player</strong></td>
<td><strong>Strategy</strong></td>
</tr>
<tr>
<td>Frank Dux</td>
<td>Tit-for-Tat except 1/9 defect + defect on final game</td>
</tr>
<tr>
<td>Adamo</td>
<td>Count defects and cooperates. If defects > cooperates then defect. Also, defect every other move.</td>
</tr>
<tr>
<td>SAY WHAT AGAIN?</td>
<td>Effectively, always defect.</td>
</tr>
<tr>
<td>SummaNoid 3000</td>
<td>Tit-for-Tat</td>
</tr>
<tr>
<td>El Santo</td>
<td>Track +/- of defect/cooperate. Cooperate when opponent cooperates more than defects. (random component too).</td>
</tr>
<tr>
<td>Spaghetti Coder</td>
<td>Cooperate when opponents overall cooperate percentage greater than defect percentage.</td>
</tr>
<tr>
<td>Sharbaugh</td>
<td>Track % mean. <br><br> When percentMean Defect. <br><br> When percentMean > 75% ==> Defect. <br><br> When percentmean > 25% && Be randomly mean as much as they are. i.e. if they are mean 40% of the time, be mean 40% randomly.</td>
</tr>
</tbody>
</table>
<p>Â </p>
<p>Again, if you're so inclined, you can just run the following (on a Windows machine, sorry!) from the root to play all these players against each other:<br> <code class="customCode"><br> > spd.bat<br> </code></p>
<h3>Results</h3>

<p>When you run the tournament in basic (non-survivor) mode, what you'll find is that with low number of games (~100), the mostly or purely "evil" strategies always do the best:<br> <code class="customCode"><br> SAY WHAT AGAIN!: 2,482<br> SpaghettiCoder: 2,484<br> Joe Evil: 2,486<br> </code><br> It's only when you increase the number of games past about 1,000 that Sharbaugh, a opportunistic cooperator, begins to take the lead. Tagging not far behind, however, are still the evil strategies<br> <code class="customCode"><br> SAY WHAT AGAIN!: 24,596<br> Joe Evil: 24,606<br> SpaghettiCoder: 24,628<br> Sharbaugh: 24,855<br> </code><br> There are a few interesting observations to be gleaned here.</p>

<p>First, the Tit-for-Tat strategies never do well because they can't establish trust with anyone. SummaNoid 3000, a pure Tit-for-Tat wants to cooperate with Frank Dux, but as soon as Frank Dux randomly defects, SummaNoid 3000 never forgives, and they end up defecting against each other the rest of the way and miss out on the potential benefit of cooperation.</p>

<p>Meanwhile, the evil strategies thrive by preying on the blissfully, ignorant players (Mr. Nice Guy and Bob Backstabber). When you take these players out of the mix, however, the mean strategies fall to the bottom, and the cooperators like Sharbaugh, Frank Dux, and SummaNoid 3000 float to the top. Here's a sample 1,000-game round without the "dumb" strategies:<br> <code class="customCode"><br> Rupert Random: 13,459<br> El Santo: 15,012<br> Adamo: 15,014<br> SAY WHAT AGAIN!: 1,5014<br> SpaghettiCoder: 15,020<br> Frank Dux: 15,041<br> SummaNoid 3000: 15,157<br> Sharbaugh: 15,443<br> </code><br> In other words, when others are very nice but not very smart, it's easy to get away with being "mean"!</p>

<p>There was also an optional survivor mode component to the game, where at the end of each round each player could vote one other player "off the island". Strategies differed as to whom to vote off. Some voted off the "meanest", some the "nicest", and some whomever did best against them. Because many players had non-deterministic (random) strategies, there didn't seem to be any predictability in these games. Although El Santo and Sharbaugh seem to win more often (from what it seems), other players also win from time to time. It's not clear if there's a conclusion to draw from the survivor mode.</p>

<p>In the end, we could analyze and play this game for hours/days/weeks more, but alas the fun had to end, and we had to get back to real work. It was a ton of fun, and hopefully we'll do it again soon. Let me know if you want to use the source code here, or just share an AI challenge that you've played.</p></span>
        </div>				]]>			</description>
			<pubDate>Mon, 30 Sep 2013 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2013/ai-challenge-prisoners-dilemma.php</guid>
		</item>
		<item>
			<title>Expectations and the Endowment Effect</title>
			<link>http://www.bennorthrop.com/Essays/2013/expectations-and-the-endowment-effect.php</link>
			<description>
				<![CDATA[				<p>Managing the expectations of the customer is one of the trickiest things in software development.  Imagine this scenario...</p>

<p class="indentableSubtle">
You're just a few days into a sprint.  Your customer, a reasonable enough guy, identifies a new feature related to something your working on.  It's small, maybe just a 3 story pointer in a 60 point sprint, but you have a good amount on your plate as it is.  
<br/>
<br/>
Since you aim to please, however, you let the customer know that you'll give it a shot.  If things are tight at the end of the sprint though, it'll need to get pulled from scope.  No big deal.
<br/>
<br/>
Sure enough, the end of the sprint comes, and you're swamped.  You can finish everything you originally committed to, but you won't have time to finish the extra feature.  You let the customer know, thinking it'll be a non-issue.  To your surprise though, he's actually kind of torqued.  But you're delivering what you originally committed to!
</p>

<p>
What happened here?  You never truly committed to the feature in the first place, it was really just a bonus.  Why would the customer be upset?  
</p>

<p>At least part of the explanation comes from <a href="http://en.wikipedia.org/wiki/Prospect_theory">prospect theory</a>, and it's something called the <a href="http://en.wikipedia.org/wiki/Endowment_effect">endowment effect</a>.  In a nutshell, the endowment effect asserts first that we hate losses more we than enjoy gains, and second that both losses and gains are calculated not absolutely, but relative to some <a href="http://en.wikipedia.org/wiki/Anchoring">reference point</a>.  What does all this mean?  Let's look back at the example.</p>

<p>Initially, the business owner expects 60 <a href="http://agilefaq.wordpress.com/2007/11/13/what-is-a-story-point/">story points</a> to be delivered, and he's content with this.  A few days into the sprint, when you tentatively commit to the new feature, you do indeed make him happy.  To put it in numbers, say...

<p class="indentable" style="font-family: courier new">
3 story point gain = 10 "happiness points"
</p>

<p>
At this point, however, his reference point shifts.  Whereas he was initially expecting 60 story points to be delivered, his mind is now attached to 63 points.  
</p>

<p>
Fast forward to the the end of the sprint.  You realize you can't actually deliver the extra feature, and so you take it out of scope.  You assume the customer is thinking in absolute terms - he started out expecting 60 story points to be delivered, and that's what he's getting.  This is where you're wrong.</p>

<p>
The customer at the end of the sprint is only thinking from his current reference point, which is 63 story points, and so he perceives you not completing the new feature as a 3 point loss.  Further, since people <b>dislike losses more than they like gains</b>, that 3 point loss doesn't just "cancel out" the 3 point gain from before, but it actually looms larger.  Again, in numbers, prospect theory explains that he might <i>feel</i> the loss like...
</p>
<p class="indentable" style="font-family: courier new">
3 story point loss = -20 "happiness points"
</p>
<p>
In other words, because you "gave" the customer the new feature, and then took it away, he is less happy than if you never tried in the first place!  Rationally speaking it doesn't seem like it should make a difference to him (+3 story points - 3 story points = 0!).  Given how our cognitive apparatus perceives losses, however, it does!  
</p>

<p>
This effect shows up all over.   Paraphrasing <a href="http://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman/dp/0374533555">an example</a> from the famous economist <a href="http://en.wikipedia.org/wiki/Daniel_Kahneman">Daniel Kahneman</a>, imagine your favorite football team is in the playoffs.  You'd be willing to pay $300 to go, and fortuitously you find a stranger to sell you a ticket for that much.  A few days later, the game is getting a ton of hype, and you learn that tickets are going for $1,000 online.  Do you sell your ticket?  No!  Even though you valued the <i>getting</i> of the ticket at $300, once you <i>have</i> the ticket, you value the <i>losing</i> of the ticket at more than $1,000.  In other words, once you have something, you hate to lose it. 
</p>

<p>
What does this mean for us in software development?  Well, as developers we need to be conscious of our customers' inherent <a href="http://en.wikipedia.org/wiki/Loss_aversion">loss aversion</a>, and so always <b>be cautious when setting reference points of any kind</b>.  This is not just limited to scope issues, either.  If you tell the customer, for example, that you'll be done with some task in 5 days, you've just set the reference point.  Finishing in 4 days (a gain of 1 day) will make the customer happy, but not as unhappy as will finishing in 6 days (a loss of 1 day).  Losses rule!
</p>

<p>
In the end, it boils down to the advice a colleague gave me on one of my first projects: "under-promise and over-deliver".  With only our words, we define the expectations others will use to measure us by.  Understanding loss aversion and the endowment effect, we can use this to our advantage!  
</p>

<h3>Recent Posts</h3>
<ol>
<li><a href="http://www.bennorthrop.com/Essays/2013/consistency-and-innovation-pick-one.php">Consistency and Innovation: Pick One</a></li>
<li><a href="http://www.bennorthrop.com/Essays/2013/pair-programming-my-personal-nightmare.php">Pair Programming - My Personal Nightmare</a></li>
<li><a href="http://www.bennorthrop.com/Essays/2012/the-user-interface-and-the-halo-effect.php">The User Interface and the Halo Effect</a></li>
</ol>				]]>			</description>
			<pubDate>Tue, 17 Sep 2013 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2013/expectations-and-the-endowment-effect.php</guid>
		</item>
		<item>
			<title>Consistency and Innovation: Pick One</title>
			<link>http://www.bennorthrop.com/Essays/2013/consistency-and-innovation-pick-one.php</link>
			<description>
				<![CDATA[				<p>
We start every project with good intentions, but invariably our code unravels into a <a href="http://www.laputan.org/mud/">big ball of mud</a>.  It's disconcerting, and yet unavoidable.  We sheepishly explain to the developer who joins the project 2 years in, "well, you see, back when we started, we just didn't anticipate X or Y or Z would change", and "we didn't have time to go back".
</p>
<p>
It can all start with a simple text box...
</p>

<p class="codeSample">
TextBox textBox = new TextBox();
</p>

Initially, that's all we need.  But of course there's styling to be added, and also a label, so maybe we just tack on a few lines after each text box initialization.  No big deal.

<p class="codeSample">
TextBox textBox = new TextBox();<br/>
textBox.setStyle("txt-standard");<br/>
Label lbl = new Label("First Name:");<br/>
</p>

After creating a handful of screens (each with a dozen or so text boxes), an observant developer opines: "hey, we could save a lot of typing if we'd just create a custom TextBox wrapper which includes the style and the label", like this:

<p class="codeSample">
TextBox textBox = new AcmeTextBox("First Name:", "txt-standard");  
</p>

<p>
And there it is.  This trivial example captures the essence of a problem that occurs over and over on every project, large and small, team or solo.  The problem is: <b>what do we do when we find a better way of doing things</b>?  Note that "better" can mean not just more maintainable, but more extensible, scalable, faster, etc.  Of course the decision seems obvious (go with the better solution!), but it's not always that easy.  Just consider your choices for the TextBox example:
</p>
<p class="indentable">
1. <i>Refactor</i>: </b>Go back to each TextBox initialization, and replace with the AcmeTextBox.
<br/>
<br/>
2. <i>Live and Let Live.</i> Use the AcmeTextBox on all new screens, but leave the old code as is. 
<br/>
<br/>
3. <i>Stay the Course</i>: Stick with the old, clunkier TextBox initialization.
</p>

<p>
The lead developer will argue: if it's genuinely a better way of doing things, then let's go back and refactor the old for the new.  Not only is it a better solution, but there's no worry that someone will inadvertently copy-and-paste from the old code, and propagate the inferior solution.  (Option 1: innovation + consistency)
</p>
<p>
But "not so fast", the PM will say. If the screens functioned correctly before, don't touch that code!  Regression testing costs time and money, and there are deadlines to meet.  If you want the better solution moving forward, great, but let sleeping dogs lie.  (Option 2: innovation + inconsistency)
</p>
<p>
Enter the curmudgeon developer: it'll just be confusing to do the same thing in two different ways, so let's just deal with a little extra typing and keep things consistent. (Option 3: no innovation + consistency)
</p>
<p>
So who's right?
</p>
<p>
The PM and the curmudgeon developer have valid points, there are costs to change, but if we heed their advice too often, it's a quick slide down the slippery slope into architectural mud.  A codebase <a href="http://robdmoore.id.au/blog/2012/09/01/consistency-maintainability/">rife with inconsistency</a> is a maintenance nightmare.  So too is a codebase that <a href="http://c2.com/cgi/wiki?ConstantRefactoringIsaGoodThing">never evolves</a>.  
</p>
<p>
In our gut, we want to listen to the tech lead, and always go back and refactor, but we realize this is a tough sell for all stakeholders.  How do we make the case then?  Well, we must show not only that it's worthwhile to implement the new solution:
<p class="indentable">
Cost of Solution < Value of Solution<sub>(new code)</sub>
</p>
<p>
...but also that there's benefit to go back and refactor the old code.  In other words:
</p>
<p class="indentable">
Cost of Solution + Cost of Refactoring < Value of Solution<sub>(new)</sub> + Value of Solution<sub>(old)</sub>
</p>
<p>
The problem is, that while the cost side of the equation is usually a pretty tangible number incurred in the short term (e.g. it'll cost 20 hours to refactor all instances of TextBox to AcmeTextBox), the value side of the equation is neither easy to quantify nor realized in any near-term horizon (e.g. how much productivity is actually gained by using AcmeTextBox everywhere?  And how do you convey this to the PM or QA lead?). Getting all stakeholders to buy into refactoring, therefore, is a non-trivial leap of faith: it must pay for something <i>now</i> in hopes of getting some return down the road.    
</p>
<p>
What can we do?  I think we need to <b>address both sides of the equation</b>.  
</p>
<p>On the left side of the equation, we need to to work vigilantly to reduce the cost of refactoring, by committing to continuous integration, unit tests, etc..  If it's cheap to refactor, then there's less of a burden to show that consistency is worthwhile.
</p>
<p>
On the right side of the equation, we can do a few things.  First, we can try to use data to help quantify the value of consistency (i.e. maintainability) using tools like <a href="http://www.sonarsource.com/">Sonar</a> or <a href="http://www.bennorthrop.com/cruft4j/index.php">Cruft4J</a>, and also concepts like <a href="http://martinfowler.com/bliki/TechnicalDebt.html">technical debt</a>.  If stakeholders understand the value, it'll be easier to weigh against the costs of refactoring.  Second, we need to build trust by <a href="http://continuousdelivery.com/">continuously delivering value</a> to the business side, ensuring that refactoring expeditions are not done to the exclusion of tangible functionality.   Philippe Kruchten presented an interesting approach for doing this using a <a href="http://www.infoq.com/news/2010/05/what-color-backlog">color coded backlog</a>.
</p>
<p>
In the end, the approach of going-back-to-implement-the-new-solution-everywhere won't always win the day.  The cost of refactoring will be too high, or the value of consistency won't be appreciated.  In these cases, you'll be stuck with the age-old software development dilemma: consistency or innovation.  I usually side with the latter, but I'd love to hear your thoughts!
</p>
<h3>Recent Posts</h3>
<ol>
<li><a href="http://www.bennorthrop.com/Essays/2013/pair-programming-my-personal-nightmare.php">Pair Programming - My Personal Nightmare</a></li>
<li><a href="http://www.bennorthrop.com/Essays/2012/the-user-interface-and-the-halo-effect.php">The User Interface and the Halo Effect</a></li>
<li><a href="http://www.bennorthrop.com/Essays/2012/velocity-and-story-points-they-dont-add-up.php">Velocity and Story Points - They don't add up!</a></li>
</ol>				]]>			</description>
			<pubDate>Mon, 19 Aug 2013 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2013/consistency-and-innovation-pick-one.php</guid>
		</item>
		<item>
			<title>Pair Programming - My Personal Nightmare</title>
			<link>http://www.bennorthrop.com/Essays/2013/pair-programming-my-personal-nightmare.php</link>
			<description>
				<![CDATA[				<p>
Since the dawn of <a href="http://en.wikipedia.org/wiki/Extreme_programming">XP,</a>  I've read about the <a href="http://c2.com/cgi/wiki?PairProgramming">benefits</a> of Pair Programming.  Evangelists have told us that it will improve code quality, help knowledge dissemination, and even boost productivity, all while cultivating deep, soulful bonds between developers (see: <a href="http://www.youtube.com/watch?v=dYBjVTMUQY0">spooning</a>). 
</p>
<p>
Those who reject pair programming are <a href="http://blogs.atlassian.com/2009/06/pair_programming_is_kryptonite/">assumed to be</a> cowboys, slackers, or social recluses.  Well, I'm none of these (at least I don't think), but yet I still <i>hate</i> the idea of Pair Programming.  For what it's worth, here's why... 
</p>

<p>
We are no longer a culture that respects silence.  The extroverts have won.  Everything must be done collaboratively.  Everyone must be available to everyone, all the time.  There should be no more personal space, and no ownership of work.  Basically, we believe that two heads are always better than one.  
</p>

<p>
And yet it should be obvious to us that this is not always the case.  Just in the world of programming, some great works of innovation and craftsmanship have sprung not from a team or a pair, but from the efforts of one person.  I think about <a href="http://ant.apache.org/">Ant</a>, a huge leap forward for the Java community at the time, developed by <a href="http://en.wikipedia.org/wiki/James_Duncan_Davidson">one guy</a> on a flight from Europe to the US (<a href="#references">1</a>).  Or a tad more current, consider <a href="http://en.wikipedia.org/wiki/Notch_%28game_designer%29">Notch</a> of Minecraft, <a href="http://www.time.com/time/specials/packages/article/0,28804,2094921_2094923_2094924,00.html">Marco Arment</a> of Instapaper, or <a href="http://nerdbusiness.com/blog/10-reasons-why-duckduckgo-awesome">Gabriel Weinberg</a> of DuckDuckGo: all solo achievements (<a href="#references">2</a>).  In fact, one of the most influential programmers (if not people) in the world, Steve Wozniak, famously advocates: 
</p>
<p class="indentableSubtle">
"Work alone. Not on a committee. Not on a team."  
</p>

<p>
Going further, some of the greatest thinkers in science and art are of the heads-down (i.e. introvert) variety - think Darwin, Einstein, Newton, or heck, even Dr. Seuss (<a href="#references">3</a>).  Even John Steinbeck chips in here:
</p>

<p class="indentableSubtle">
Nothing was ever created by two men. There are no good collaborations, whether in music, in art, in poetry, in mathematics, in philosophy. Once the miracle of creation has taken place, the group can build and extend it, but the group never invents anything.  The preciousness lies in the lonely mind of a man. (<a href="#references">4</a>)
</p>

<p>
Ok, I'm waxing philosophic here, but back to our own little corner of the world, software development, why would we believe, as some argue, that hyper-collaboration (e.g. pair programming) is a precondition to quality or productivity when we can readily think of so many counterfactuals?  Why, for some, is Pair Programming a "must do", all the time?
</p>

<p>
I believe it's just a reflection of one's own personal psychology.  Simply: some people enjoy this style of work, and so they prescribe it, vociferously, for everyone.  
</p>

<p>
The truth is, however, that <a href="http://www.ted.com/talks/susan_cain_the_power_of_introverts.html">one third of us</a> are introverts (and probably more for programmers!).  In general, we not only prefer but thrive when working in solitude.  It's not that we don't like people, it's that our brains are wired to be <a href="http://en.wikipedia.org/wiki/Extraversion_and_introversion">more disrupted by stimulation</a> (and, for good or bad, this includes pairing).  For us, doing quality work is about getting and staying in "<a href="http://en.wikipedia.org/wiki/Flow_(psychology)">the zone</a>".  When we do, we're highly productive.  When we don't, we flail.  
</p>

<p>
Demarco and Lister, in their famous <a href="http://www.amazon.com/Peopleware-Productive-Projects-Second-Edition/dp/0932633439">Coding War Games</a> experiment, demonstrated just this - the best predictor of quality for programmers, they found, was not years of experience or salary but rather how quiet their office environment was.  
</p>

<p>
This used to be a respected insight.  In fact, #8 on the <a href="http://www.joelonsoftware.com/articles/fog0000000043.html">Joel on Software Test</a> of good places to work is "Do programmers have quiet working conditions?"  Sadly, however, the culture of hyper-collaboration has rolled over our better sensibilities, and to be perfectly honest, I think it kind of sucks.  
</p>

<p>
Pair Programming, an extension of this "everything-together" culture, has permeated our thinking to the extent that many think that one person working in isolation is not just ineffective, but boring to boot.  For me, it's the opposite.  My best work is done in solitude, and the state of flow is what I enjoy most about being a programmer.  It's not about being a "cowboy", or thinking I'm above mistakes.  I'm a huge advocate of rigorous code reviews, and I benefit daily from the insights of others.  It's just that the hyper-collaborative state of pair programming doesn't make me a better (or happier) programmer.  Please take my word for it.  
</p>
<p>
When people describe pair programming as a practice that <i>they</i> benefit from, cool, I get that.  But when they take the next leap and advocate (or mandate) the practice for me, because they "know"  I'll benefit from it (and have "data" to prove it!), slow down.  The methods by which people produce quality work are as varied as we are.  Consider some great achievements in the world (or just on your project!) and this should be obvious.  To claim that this extrovert's ideal of pair programming is a "best practice" for all is foolish, I don't care what the agile dogmatists say. </p>
<a name="references"></a>
<h3>References</h3>
<ol>
<li><a href="http://www.amazon.com/Ant-The-Definitive-Guide-Edition/dp/0596006098/ref=sr_1_2?ie=UTF8&qid=1370960108&sr=8-2&keywords=java+ant">Ant: The Definitive Guide</a>, Steve Holzner
<li><a href="http://techcrunch.com/2012/03/03/pair-programming-considered-harmful/">Pair Programming considered harmful?</a>, John Evans</li>
<li><a href="http://www.amazon.com/Quiet-Power-Introverts-World-Talking/dp/0307352145">Quiet: The Power of Introverts in a World That Can't Stop Talking</a>, Susan Cain</li>
<li><a href="http://www.amazon.com/East-Eden-John-Steinbeck/dp/0142000655/ref=sr_1_1?s=books&ie=UTF8&qid=1370896990&sr=1-1&keywords=east+of+eden">East of Eden</a>, John Steinbeck
</ol>
<h3>Recent Posts</h3>
<ol>
<li><a href="http://www.bennorthrop.com/Essays/2012/the-user-interface-and-the-halo-effect.php">The User Interface and the Halo Effect</a></li>
<li><a href="http://www.bennorthrop.com/Essays/2012/velocity-and-story-points-they-dont-add-up.php">Velocity and Story Points - They don't add up!</a></li>
<li><a href="http://www.bennorthrop.com/Essays/2011/group-polarization-and-software-development.php">A Room Full of Techies</a></li>
</ol>				]]>			</description>
			<pubDate>Tue, 11 Jun 2013 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2013/pair-programming-my-personal-nightmare.php</guid>
		</item>
		<item>
			<title>Keeping Code Clean with Cruft4J</title>
			<link>http://www.bennorthrop.com/Essays/2013/keeping-code-clean-with-cruft4j.php</link>
			<description>
				<![CDATA[				<p>If you're working on a system of enterprise scale, then you're probably "fighting the good fight" against <a href="http://pragprog.com/the-pragmatic-programmer/extracts/software-entropy">code entropy</a>. Tools like <a href="http://pmd.sourceforge.net/">PMD</a>, <a href="http://findbugs.sourceforge.net/">FindBugs</a>, <a href="http://www.sonarsource.org/">Sonar</a>, and the like are excellent weapons in this battle. Each of these tools gives a slightly different perspective of code rot; some show instances of dormant bugs, others violations of coding best practices, or others deviations from style conventions. All that's left is to do is just go in there and clean it up. So get to it!</p>
<!--more-->
<p>Unfortunately, as we know, it's just <strong>not that easy</strong>. Cleaning up code takes work, and every hour of cleaning up code is an hour of not adding functionality. This makes Project Managers and Business Owners squirm (justifiably!). Additionally, cleaning up code is also risky, since a line of code changed is also a line of code that could break. And this, of course, makes QA nervous.</p>
<p>The point is that although cleaning up code is inherently a developer activity, it requires <em>team</em> buy-in. And to get this buy-in, you need to prove to Project Managers, Business Owners, and QA that it's a worthwhile endeavor. Even if they accept the concept of <a href="http://martinfowler.com/bliki/TechnicalDebt.html">technical debt</a> in principle, before they "ok" your code cleaning expedition they probably still want to know:</p>
<ul>
<li>How big is the problem (i.e. how does our code quality compare to other systems)?</li>
</ul>
<div style="margin: 5px;"></div>
<ul>
<li>Are things getting better or worse?</li>
</ul>
<div style="margin: 8px;"></div>
<p>Armed with just a long list of obscure coding violations from PMD and the others, these questions are difficult to answer. Sure, your system has 1,358 violations, but is that good or bad? Are these violations even important?</p>
<p>This is where a tool called <a href="http://www.bennorthrop.com/cruft4j/index.php">Cruft4J</a> can help. Cruft4J is a static source code analysis tool, like the others, but instead of a detailed list of coding violations, Cruft4J spits out just <a href="http://www.bennorthrop.com/cruft4j/index.php#score">one score</a>:</p>
<div style="margin: 0px 0px 10px 50px; font-family: courier new;">Cruft Score = (Complexity + Copy-Paste ) / Lines of Code</div>
<p>To answer the first question, how big the problem is, <a href="http://www.bennorthrop.com/cruft4j/index.php#command-line">running Cruft4J once</a> will give you a score which you can compare against some <a href="http://www.bennorthrop.com/cruft4j/index.php#benchmarks">benchmarks of open source code</a>. Obviously, the cruft score isn't a <em>perfect</em> measure of code quality, but if your system scored a 200, and the average score is 52, you know something is probably wrong.</p>
<p>To answer the second question, are things getting better or worse, running Cruft4J over time (or better yet, hooking it into your build) makes it easy to spot trends over time, so you can understand whether the ship is headed in the right or wrong direction.</p>
<p>Now there are other tools, like <a href="http://www.crap4j.org/">Crap4J</a> and Sonar's <a href="http://www.sonarsource.org/evaluate-your-technical-debt-with-sonar/">Technical Debt</a>, that too provide a single score. These tools, however, include factors that, in my opinion, are sometimes dubious indicators of code quality. For instance, Sonar's TD considers the percentage of methods that have Javadoc - but just because a method has a Javadoc comment doesn't mean that Javadoc comment is actually useful! Cruft4J, by contrast, stands on the unassailable principles of <a href="http://en.wikipedia.org/wiki/Decomposition_%28computer_science%29">Decomposition</a> and <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">Don't Repeat Yourself</a>. It's never the case that a complex method could not be broken down, or that copy-and-pasting code is preferable to other forms of re-use.</p>
<p>In the end, Cruft4J is not <em>the solution</em>, but instead a <strong>vehicle for getting the conversation started</strong>. As Business Owners and Managers understand the extent of the code rot, a better case can be made to not only clean code up, but to invest in processes that prevent bad code in the first place (e.g. code reviews, unit testing, etc.). Anyway, I hope it helps, and I'd love to hear your thoughts.</p>
<p><em>A final note: Cruft4J was built as part of an internal initiative we call Summa Labs. In Summa Labs, we work on side projects, big or small, for the purpose of honing our technical skills, collaborating with others, building cool stuff, or just having fun. If you're interested in Summa or Summa Labs, <a href="http://summa-tech.com/bestPlaceToWork.php">contact us</a>!</em></p>				]]>			</description>
			<pubDate>Tue, 04 Jun 2013 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2013/keeping-code-clean-with-cruft4j.php</guid>
		</item>
		<item>
			<title>The User Interface and the Halo Effect</title>
			<link>http://www.bennorthrop.com/Essays/2012/the-user-interface-and-the-halo-effect.php</link>
			<description>
				<![CDATA[				<p>If you've been a software developer for even a small time, you've undoubtedly lived this frustrating scenario...</p>

<p class="indentableSubtle">You've been working feverishly to implement a new feature for your customer.  There's some crazy complexity in the business logic, and a very simple UI as well.  It's a lot of work.  <br/><br/>

With a herculean effort, you just about meet your deadline.  The business logic is bullet-proof, but the UI is still a little rough.  No worries though, that's the easiest and least risky part.  <br></br>

You head off to demo it for the customer.  They immediately start picking at the UI: "the alignment of this column is off", "this label should be bold", and so on.  Before they even get to the actual functionality (the meat of the work!), you can tell they're already a little underwhelmed.  <br/> <br/>

In the end, everything works great, just a few minor UI glitches.  You know it's truly a big success that it's even functional, but the customer isn't ecstatic, and you can't help but feel a little dejected.  
</p>

<p>So is it reasonable to feel this way?  Yeah, probably.  But it shouldn't be unexpected.  As most seasoned developers know, the user interface carries an incommensurate amount of weight in terms of the customer's perception of the quality and completeness of the product.  One reason this is true is due to something called the <a href="http://en.wikipedia.org/wiki/Halo_effect">Halo Effect</a>. </p>

<p>In a nutshell, the Halo Effect is a built-in <a href="http://en.wikipedia.org/wiki/Cognitive_bias">cognitive bias</a> that drives us to believe that if our initial impression of something (or someone) was favorable, the rest will be favorable as well.  For example, <a href="http://dtrebouxclasses.pbworks.com/w/file/fetch/50029614/sigall%20and%20ostrove.pdf">plenty</a> <a href="https://pantherfile.uwm.edu/dermer/public/vita/dermer_beauty.pdf">of</a> <a href="http://psycnet.apa.org/journals/psp/24/3/285/">studies</a> have shown that we're more likely to confer positive traits (like intelligence, creativity, etc.) to good looking people, even when we know little (or nothing!) about them other than their appearance. </p>  

<p>Or consider another example adapted from a <a href="http://www.all-about-psychology.com/solomon-asch.html">famous experiment</a> by Solomon Asch: imagine there are two people vying for a job, and all you know are a few attributes.  Person A is...</p>

<p class="indentable"><i>intelligent, inquisitive, calm, serious, passive, unambitious</i></p>

<p>...and Person B is...</p>

<p class="indentable"><i>unambitious, passive, serious, calm, inquisitive, intelligent</i></p>

<p>Without thinking too deeply, who would you hire?  Your intuition probably steered you to Person A, but if you look closely, both A and B have the same exact attributes, just in opposite orders.  Why would we perceive them differently?</p>

<p>Well, after reading just one or two characteristics, we already begin to form a general impression of the person.  Subsequent characteristics can serve to enrich this view if they are consistent with the initial characteristics, but if they conflict then they get filtered out (or at least carry less weight).   In other words, our brains <a href="http://www.bennorthrop.com/Essays/2010/cognitive_fluency.php">prefer coherence</a>, and <a href="http://en.wikipedia.org/wiki/Cognitive_dissonance">disregard dissonance</a>. </p>

<p>Back to the world of software development, it's now more clear why minor user interface peccadillos (a typo in a label, for example) can significantly impact a customer's perception of the overall quality or even value of the software we build, to an extent that seems capricious or unfair.  That's just how our brains work.</p>

<p>Essentially, the <b>user interface is the physical appearance of our applications</b>, and as such, customers will use it to form their initial impressions of the application as a whole.  Once this impression is formed, it's difficult to undo.  If the user interface is organized, clean, and pleasing, the customer will naturally assume the system behind it is too; but the opposite is true as well.  </p>  

<p>In the end, especially if you're early on with a customer and trust hasn't been completely established, don't focus on the back-end to the exclusion of the front-end, even if the UI is a cinch.  That mis-aligned column may only take 15 seconds to fix, but it'll be worth a whole lot more in terms of your customer's perception of quality!</p>				]]>			</description>
			<pubDate>Tue, 04 Dec 2012 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2012/the-user-interface-and-the-halo-effect.php</guid>
		</item>
		<item>
			<title>Velocity and Story Points - They don't add up!</title>
			<link>http://www.bennorthrop.com/Essays/2012/velocity-and-story-points-they-dont-add-up.php</link>
			<description>
				<![CDATA[				<p>I love Agile's idea of <a href="http://en.wikipedia.org/wiki/Velocity_tracking">velocity</a> in <i>theory</i> - that after accumulating a few weeks/months of data, a team can derive the average number of <a href="http://agilefaq.wordpress.com/2007/11/13/what-is-a-story-point/">story points</a> it can implement per sprint, and then use this as a basis for knowing both how much it can commit to in the next sprint (short term) and also when the project will be finished (long term).  </p>

<p>In <i>practice</i>, however, I believe any calculation of velocity (based in story points) is doomed to be dangerously inaccurate and misleading for either the short or long term.  Here's why... </p>

<p>The first problem is that <b>story points are not additive</b>.  Mike Cohn touches on (but does not fully address) this in a <a href="http://www.mountaingoatsoftware.com/blog/seeing-how-well-a-teams-story-points-align-from-one-to-eight">recent post</a>.  Using his example, imagine a team that uses story point buckets of 1, 2, 3, 5, and 8.  Further, consider the median number of hours to complete <a href="http://en.wikipedia.org/wiki/User_story">user stories</a> of each size:</p>

<table border="1"  align="center" class="simpleTable" >
<tr>
  <th>Story Points</th>
  <th>Median Hours</th>
</tr>
<tr>
  <td>1</td>
  <td>21</td>
<tr>
<tr>
  <td>2</td>
  <td>52</td>
<tr>
<tr>
  <td>3</td>
  <td>64</td>
<tr>
<tr>
  <td>5</td>
  <td>100</td>
<tr>
<tr>
  <td>8</td>
  <td>111</td>
<tr>		
</table>
<br/>

<p>Now assume your team's velocity is determined to be 16 points.  It would <i>seem</i> that you could pluck any combination of user stories off the <a href="http://www.mountaingoatsoftware.com/scrum/product-backlog">backlog</a> (according to the business owner's prioritization, of course!), and be fairly confident that you could complete this work so long as the stories all sum to 16 points.  It's easy to illustrate, however, why this doesn't work.  For example, take just two different combinations of stories:</p>

<table border="1"  align="center" class="simpleTable" >
<tr>
  <th>Story Combination</th>
  <th>Actual Hours</th>
</tr>
<tr>
  <td>8, 8 = 16</td>
  <td>111 + 111 = <b>222</b></td>
</tr>
<tr>
  <td>5, 3, 2, 2, 2, 1, 1 = 16</td>
  <td>100 + 64 + 52 + 52 + 52 + 21 + 21 = <b>362</b></td>
</tr>
</table>
<br/>

<p>Note that although the story points both sum to 16, the actual hours differ significantly: 222 hours for the first combination of stories and 362 for the second.  This is not a negligible amount!  It could very realistically cause a delay in a release (or alternatively, a copious amount of slack time for the development team).  Either way, something is wrong.</p>

<p>The root problem here is in the correspondence of story points to actual hours.  To be able to calculate velocity, it must be the case that story points not only preserve a relative ordering, but their numeric ratios as well.   In other words, it must be true that two 1 point stories equals the same amount of effort as one 2 point story.  Unfortunately, story points in practice are little more than <a href="http://en.wikipedia.org/wiki/Ordinal_number">ordinal values</a> - e.g. we can rely on a 2 point story being bigger than a 1 point story, but not necessarily a 2 pointer being twice as big as a 1 pointer.  </p>

<p>In general, the worse this correspondence between story points and actual hours is on your project, the more unreliable your velocity will be.  To ensure that the correspondence is consistent, therefore, a project manager must be vigilant about calculating these statistics (as in the table above) and then presenting them to the team, so that the team can best adjust their estimates (for example, using the data above, if the team wanted to keep its notion of a "1", then it would need to adjust down its assessment of a "2").</p>

<p>Assume then that the correspondence between story points and actual hours is perfect.  There's still a second problem: <b>teams very seldom track <i>actual</i> hours</b>.  Instead, "actuals", as in the example above, are most often derived from the <a href="http://www.mountaingoatsoftware.com/blog/sprint-and-release-planning-should-be-in-different-units">hour-based task estimates</a> given during the <a href="http://www.mitchlacey.com/intro-to-agile/scrum/sprint-planning-meeting">planning phase</a> to tasks.  For example, a simple "Add order" user story might be broken into three tasks, and each of these tasks would be given hour estimates prior to starting the sprint.
</p>

<ul>
  <li>Implement UI (24 hours)</li>
  <li>Implement business logic (10 hours)</li>
  <li>Test (4 hours)</li>
</ul>

<p>Summing all these tasks, the project manager would get the total number of hours for that story, which is then used to <a href="http://en.wikipedia.org/wiki/Burn_down_chart">burn down</a> from.  The problem is, of course, these hour estimates seldom map to how long these tasks <i>actually</i> took, and so using these "actual hours" to measure the correspondence of story points to actual hours will be spurious.  Again, velocity is chimerical.</p>

<p>Finally, a third problem, as a number of experts have <a href="http://swreflections.blogspot.com/2012/06/agile-estimating-story-points-and-decay.html">pointed out</a>, is that a team's assessment of <b>story points adjust over time</b>.  For example, what the team used to think of as a "2" a few months back may now be considered a "3".  This type of adjustment is fine, again, if story points are only to be used as relative values, but if they are used to calculate velocity, it simply destroys any hope for accuracy, because it is simply not mathematically valid to add them together.</p>

<p>As an analogy, if half-way through your sophomore year your college switched from a 4 point scale to a 5 point scale, they obviously couldn't calculate your GPA by just adding all your grades together and dividing by the number of units.  The scale changed!  Again, the point is that because story points aren't additive, velocity just doesn't work.</p>

<p>In the end, I completely understand that story points and velocity were designed specifically to be a low-ceremony estimates, and further that the purpose of agile is to spend more time delivering working software and less time on producing plans for delivering software.  That's great.  However, there seems to be a very pervasive and dogmatic belief in the robustness of velocity, and it's just not empirically warranted.  The idea is great in concept, but it's based on a the faulty premise: that story points can be used like numbers.  </p>

<p>Personally, I severely doubt that velocity can be used reliably for long term forecasting, and definitely <a href="http://www.mountaingoatsoftware.com/blog/why-i-dont-use-story-points-for-sprint-planning">not for sprint planning</a>.  Just my thoughts - what do you think?</p>				]]>			</description>
			<pubDate>Wed, 22 Aug 2012 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2012/velocity-and-story-points-they-dont-add-up.php</guid>
		</item>
		<item>
			<title>Time Zones and GWT's DateTimeFormat</title>
			<link>http://www.bennorthrop.com/Essays/2012/gwt-datetimeformat-timezone.php</link>
			<description>
				<![CDATA[				<p>Letâ€™s assume you wanted to display the userâ€™s birth date in your <a href="http://developers.google.com/">GWT</a> application. Sounds easy, right? You write a few simple lines of code in your GWT view class:</p>

<pre class="java:nocontrols"><code data-language="java">  DateTimeFormat f = DateTimeFormat.getFormat("MMM dd yyyy");
  lblDate.setText(f.format(user.getBirthDate());</code></pre>
  
<p>After testing this feature locally, everything works as expected, and so you ship it. Voila! A few days later, however, the help desk calls and says that a user is complaining that their birth date is one day off. You assume it must be a data issue, so you check the database. The userâ€™s birth date is:</p>

<pre><code>1977-06-02 00:00:00.0</code></pre>
<p>You then check for yourself within the application, and the users birthdate shows up as June 2nd, as it should. However, the user claims the apps says his birthdate is June 1st, and he has a screen shot to prove it. What the heck?</p>
<p>Well, upon further digging, you find that the user is in California, 3 time zones away from you, in New York. Seems like maybe this is the problem. You throw a few <a href="http://www.summa-tech.com/blog/2012/06/11/7-tips-for-exception-handling-in-gwt/">debug statements</a> in your app, set the Time Zone on your local machine to Pacific, and sure enough, you recreate the problem. GWT logs that the userâ€™s birth date is:</p>

<pre><code>06/01/1977 21:00 -0700</code></pre>

<p>In other words, 9pm the day before. Whatâ€™s happening is that GWT by default <a href="http://stackoverflow.com/questions/2189148/how-do-i-get-gwt-datetimeformat-to-display-using-the-server-timezone-rather-tha">uses the clientâ€™s local time zone</a> when formatting dates with <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.5/com/google/gwt/i18n/client/DateTimeFormat.html">DateTimeFormat</a>, so if a date is stored as midnight in the database for a given time zone (EST, in this case), for any time zone after the birth date will display as the day before.</p>

<p>Part of the root problem is that that storing a birth date as a <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/sql/Date.html">Java Date</a> is really overkill for most cases, since often all thatâ€™s needed is the day, month, and year. What the Java Date class gives us, instead, is some number of milliseconds relative to 1970 (plus if after, minus if before). On the server side everything would be fine, since formatting this date would use the timezone of the server, which is what the date is stored in. On the client side, however, GWT will use the timezone of the client machine, and so there could be a discrepancy.</p>

<p>Ok, back to the scenario. Armed with this knowledge, you then decide to hard-code the <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.5/com/google/gwt/i18n/client/TimeZone.html">TimeZone</a> when calling DateTimeFormat.format(). Knowing that EST is -5:00 hours from UTC/GMT, you would pass +300 minutes as an offset (note: it would seem more intuitive to pass -300, but this is <a href="http://stackoverflow.com/questions/5068701/gwt-datetimeformat-reverses-timezone-value">not the case</a>). Soâ€¦</p>


<pre class="java:nocontrols"><code data-language="java">  DateTimeFormat f = DateTimeFormat.getFormat("MMM dd yyyy");
  TimeZone est = TimeZone.createTimeZone(+300);
  lblDate.setText(f.format(user.getBirthDate(), est);</code></pre>

<p>Now, you test the change locally, this time checking for different time zones, and again feel confident that the bug is slayed and you ship the code to production. A few months later this time, youâ€™d get another call from the help desk with the same exact problem: the user complains that his birth date is displaying one day prior to his actual birth date. Argh. What changed?</p>

<p>Thinking about it, you realize that whatâ€™s different is the season! A few months ago it was summer, but now itâ€™s winter. Daylight Savings Time! What you didnâ€™t account for is that user was born in June, which is really only -4:00 hours away from UTC/GMT, but youâ€™re still offsetting -5:00 hours, and so on the client side the userâ€™s birthdate is really:</p>

<pre><code>06/01/1977 23:00 -0500</code></pre>
<p>What you need is to take into account Daylight Savings Time in your format method:</p>

<pre class="java:nocontrols"><code data-language="java">  DateTimeFormat f = DateTimeFormat.getFormat("MMM dd yyyy");
  TimeZoneConstants t = (TimeZoneConstants) GWT
     .create(TimeZoneConstants.class)
  TimeZone est = TimeZone.createTimeZone(
     t.americaNewYork());
  int offset = est.isDaylightTime(date) ? +240 : +300;
  TimeZone tz = TimeZone.createTimeZone(offset);
  lblBirthDate.setText(f.format(date, tz));</code></pre>

<p>Now, you think youâ€™d be out of the woods, but unfortunately not. A few months later, youâ€™d get yet another call from the help desk about the same freaking problem. Youâ€™re ready to lose it. Whatâ€™s going on this time? Well, this user, you realize, is older than the others. He was born on:</p>
<pre><code>1957-08-22 00:00:00.0</code></pre>

<p>â€¦but again his birthdate was displaying as the day before. Well, it turns out that GWTâ€™s <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.5/com/google/gwt/i18n/client/constants/TimeZoneConstants.html">TimeZoneConstants</a> class doesnâ€™t consider Daylight Savings Time prior to 1970, and so the isDaylightTime() always returns false, and the -5:00 hour offset is always used, causing the same exact problem.</p>

<p>At this point, there are a few viable solutions. First, you could just format the date on the server side and pass it to the client as a String. Alternatively, you could create your own custom Date class (either as a subclass to Javaâ€™s Date or otherwise) that either takes into account TimeZones or just codifies dates as day/month/year. There are a few <a href="http://stackoverflow.com/questions/2189148/how-do-i-get-gwt-datetimeformat-to-display-using-the-server-timezone-rather-tha">other possible solutions</a>, but one of these two might do the trick.</p>

<p>Anyway, I hope this post has helped you avoid this problem. Iâ€™d love to hear any strategies youâ€™ve come up with. Thanks!</p>				]]>			</description>
			<pubDate>Mon, 06 Aug 2012 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2012/gwt-datetimeformat-timezone.php</guid>
		</item>
		<item>
			<title>7 Tips for Exception Handling in GWT</title>
			<link>http://www.bennorthrop.com/Essays/2012/7-tips-for-exception-handling-in-gwt.php</link>
			<description>
				<![CDATA[				<p>Exception handling best practices in Java are pretty straight-forward by now, and for the most part this carries over into the world of <a href="https://developers.google.com/web-toolkit/">GWT</a> (since GWT is, from the end developer's perspective, just Java!). There are, however, a few tricks and gotchas that are important to be aware of. In this blog post I'll describe a few that I've encountered, but please feel free to share your own.</p>
<!--more-->
<p>Starting with the client tier and working my way to the server, here we go...</p>

<h3>1. Handle all uncaught client-side exceptions</h3>
<p>The first thing and simplest thing to do is to ensure that all unhandled exceptions bubbling out of the client tier are caught. You can accomplish this by registering an <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.4/com/google/gwt/core/client/GWT.UncaughtExceptionHandler.html">UncaughtExceptionHandler</a>, like this:</p>

<pre class="java:nocontrols">
<code data-language="java">  public class Example implements EntryPoint {
    public void onModuleLoad() {
      GWT.setUncaughtExceptionHandler(new
        GWT.UncaughtExceptionHandler() {
        public void onUncaughtException(Throwable e) {
          // do exception handling stuf
      }
      // do module loading stuff
    }
}
</code>
</pre>
<p>Pretty straight-forward. What happens if you don't set the UncaughtExceptionHandler in your application? Well, in <a href="https://developers.google.com/web-toolkit/doc/1.6/DevGuideCompilingAndDebugging">hosted mode</a>, the default handler will conveniently <a href="http://stackoverflow.com/questions/3028521/gwt-setuncaughtexceptionhandler">log the exception</a> and stack trace to the console. In web mode, however, the handler is null, and so exceptions "escape" to your browser, which is likely not the user experience you're looking for (though it does provide the opportunity to use a Javascript debugger for further diagnosis).</p>
<p>Also, be aware that your custom UncaughtExceptionHandler only takes effect <em>after</em> the onModuleLoad() returns. In other words, if there was an exception raised where the comment "do module loading stuff" is in the example above, this exception would <em>not</em> be handled using your custom UncaughtExceptionHandler that you just defined. This is a <a href="http://code.google.com/p/google-web-toolkit/issues/detail?id=1617">known issue</a>, and will not be resolved. As a work-around, if you expect exceptions could be thrown within onModuleLoads(), then you can extract the guts of onModuleLoad() to another method, and invoke it using a DeferredCommand:</p>
<pre class="java:nocontrols">
<code data-language="java">public class Example implements EntryPoint {
  public void onModuleLoad() {
    GWT.setUncaughtExceptionHandler(new
      GWT.UncaughtExceptionHandler() {
      public void onUncaughtException(Throwable e) {
        // do exception handling stuff
      }
    });
    DeferredCommand.addCommand(new Command() {
      public void execute() {
        onModuleLoad2();
      }
    });
  }

  private void onModuleLoad2() {
    // do module loading stuff
  }
}
</code>
</pre>
<h3>2. Unravel GWT's UmbrellaException</h3>
<p>Once your UncaughtExceptionHandler is set, you may notice that some of the exceptions caught are instances of GWT's <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.1/com/google/gwt/event/shared/UmbrellaException.html">UmbrellaException</a>, rather than the actual exception thrown within your code. GWT uses UmbrellaExceptions to wrap exceptions in certain cases (loops, etc.), and it nests the root exception within it. For the purpose of easier debugging and more accurate error handling, it's <a href="http://stackoverflow.com/questions/4136936/what-could-cause-an-umbrellaexception-anonymous-function-on-deployed-gwt-app">often helpful</a> to unwrap these exceptions, like this:</p>
<pre class="java:nocontrols">
<code data-language="java">GWT.setUncaughtExceptionHandler(new
  GWT.UncaughtExceptionHandler() {
  public void onUncaughtException(Throwable e) {
    Throwable unwrapped = unwrap(e);
    // do exception handling stuff
  }  

  public Throwable unwrap(Throwable e) {
    if(e instanceof UmbrellaException) {
      UmbrellaException ue = (UmbrellaException) e;
      if(ue.getCauses().size() == 1) {
        return unwrap(ue.getCauses().iterator().next());
      }
    }
    return e;
  }
}
</code>
</pre>
<h3>3. Log exceptions on the client</h3>
<p>Now that you have a handler catching your rogue client side exceptions and also a handy method to unravel them to their root causes, you'll want to actually <em>do something</em> useful with these exceptions to help developers more easily diagnose and resolve the underlying problems. While the appropriate action may differ per application (e.g. present an error dialog, email the support team, etc.), at the very least the exception should be logged. Fortunately, GWT delivers a simple but <a href="https://developers.google.com/web-toolkit/doc/latest/DevGuideLogging">powerful solution</a> for client-side logging, piggy-backing off of the standard <a href="http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0CF0QFjAB&url=http%3A%2F%2Fdownload.oracle.com%2Fjavase%2F1.4.2%2Fdocs%2Fguide%2Futil%2Flogging%2Foverview.html&ei=IFfST6ykBomW2QXB58iiDw&usg=AFQjCNGtAfaszw3fh9fu0lz9jOg_cc_6Gg">java.util.logging package</a>. Plugging a logger into the UncaughtExceptionHandler is easily accomplished:</p>
<pre class="java:nocontrols">
<code data-language="java">public class Example implements EntryPoint {

  private Logger logger = Logger.getLogger("");

  public void onModuleLoad() {
   GWT.setUncaughtExceptionHandler(new
     GWT.UncaughtExceptionHandler() {
     public void onUncaughtException(Throwable e) {
        logger.log(Level.ERROR, "Ex caught!", e);
    }
    // do module loading stuff
  }
}
</code>
</pre>
<p>Leveraging a helpful set of handlers that GWT provides, loggers can write to a number of different channels: development mode window, console, in-window pop-up, Firebug, and, the coup-de-gras, to the server(which I'll cover in a bit). These channels are easily configurable via your .gwt.xml file:</p>
<pre class="xml:nocontrols">  <inherits name="com.google.gwt.logging.Logging" />
  <set-property name="gwt.logging.logLevel"
    value="INFO" />
  <set-property name="gwt.logging.enabled"
    value="TRUE" />
  <set-property name="gwt.logging.developmentModeHandler"
    value="ENABLED" />
  <set-property name="gwt.logging.systemHandler"
    value="DISABLED" />
  <set-property name="gwt.logging.popupHandler"
    value="DISABLED" />
  <set-property name="gwt.logging.consoleHandler"
    value="ENABLED"/>
  <set-property name="gwt.logging.firebugHandler"
    value="ENABLED" />
</pre>
<p>Logging in GWT is very <a href="https://developers.google.com/web-toolkit/doc/latest/DevGuideLogging">well documented</a>, so there's no need to retread here.</p>
<h3>4. Log exceptions on the server</h3>
<p>The majority of the logging handlers write to the client side, however in a production environment this often isn't much help to you. When your users stumble upon an error, it's unlikely (and actually unsafe from a security perspective!) to expect them to look in client-side log files to help you diagnose the problem. Instead, your application should do this work for you, by logging all unexpected exceptions to the server. Fortunately, <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/logging/server/RemoteLoggingServiceImpl.html">remote logging</a> of this sort is as simple as enabling it in the .gwt.xml config file:</p>
<pre class="xml:nocontrols">  <set-property name="gwt.logging.simpleRemoteHandler"
      value="ENABLED" />
</pre>
<p>...and then defining the <a href="http://stackoverflow.com/questions/5812035/setup-a-remoteloggingservlet-in-gwt">remote logging servlet</a> in your web.xml file:</p>
<pre class="xml:nocontrols">  <servlet>
    <servlet-name>remoteLogging</servlet-name>
    <servlet-class>com.google.gwt.logging.server.RemoteLoggingServiceImpl</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>remoteLogging</servlet-name>
    <url-pattern>/your-gwt-module-name/remote_logging</url-pattern>
  </servlet-mapping>
</pre>
<p>Now, with one simple call to the log() method in your UncaughtExceptionHandler, the exception is sent automatically to your server log. Note, however, that by default it's assumed that you're using java.util.logging, which may not necessarily be the case. To hook these logs into, say, <a href="http://logging.apache.org/log4j/1.2/manual.html">Log4J</a>, check out <a href="http://www.slf4j.org/">SL4J</a>.</p>
<p>Finally, it's possible that instead of using GWT's remote logging, you may want to implement a simple custom <a href="https://developers.google.com/web-toolkit/doc/latest/tutorial/RPC">RPC</a> to log (and possibly do other things - e.g. send email, etc.) when an unexpected exception is encountered. For example:</p>
<pre class="java:nocontrols">
<code data-language="java">GWT.setUncaughtExceptionHandler(new
  GWT.UncaughtExceptionHandler() {
  public void onUncaughtException(Throwable e) {
    myService.handleException(e);
  }
}
</code>
</pre>
<p>Seems straight-forward, right? Be careful! First, not all exceptions are <a href="http://docs.oracle.com/javase/1.4.2/docs/api/java/io/Serializable.html">serializable</a> or follow the <a href="http://java.sun.com/developer/technicalArticles/Programming/serialization/">rules</a> of serializable (ugh!). For example, GWT's <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/core/client/JavaScriptException.html">JavascriptException</a> inherits Serializable, but doesn't implement a public no-arg constructor, so when you try to send this over the wire via your RPC, a run-time Serialization exception is thrown. And since this exception would be thrown <strong>inside</strong> your exception handler, it would effectively swallowed. Second, the stack trace within an exception is <a href="http://stackoverflow.com/questions/910374/why-does-java-have-transient-variables">transient</a>, and so is lost from client to server (so if you need it on the server side, send it as a separate parameter). Which leads me to the next tip...</p>
<h3>5. Consider logging exception stack traces</h3>
<p>Of course knowing that an exception occurred isn't usually helpful unless you know exactly where it was thrown from! On the server side we take this for granted, since stack traces are typically logged by default with our exceptions. On the client side with GWT side, however, it's not so easy. When Java code gets <a href="https://developers.google.com/web-toolkit/doc/latest/DevGuideCompilingAndDebugging">compiled</a> into Javascript, it is both shrunk and obfuscated. This is obviously useful for performance and security, but from the perspective of supporting applications, it makes things much trickier. For example, instead of seeing a stack trace with method/class names and line numbers, you might get something like this:</p>
<pre> Unknown.Jq(Unknown Source)
 Unknown.Tm(Unknown Source)
 Unknown.Sm(Unknown Source)
</pre>
<p>Not too helpful! Fortunately, there are <a href="http://code.google.com/p/google-web-toolkit/wiki/WebModeExceptions">different options</a> for how GWT compiles into Javascript which provide different amounts of information for debugging. Of course nothing in life is free; the trade-offs are security and performance. If you wanted nice clean Javascript that resembles your Java code and that produces nice clean stack traces, then you can <a href="https://developers.google.com/web-toolkit/doc/1.6/FAQ_DebuggingAndCompiling#Why_is_my_GWT-generated_JavaScript_gibberish?">flip the GWT compiler</a> "style" flag to either "pretty" or "detailed", however this would obviously increase the size the Javascript (and thus take longer to download)...and any user could more easily grock your client side code. There's a nice compromise though, which is to provide file names and/or line numbers in your stack traces, but to keep the source code obfuscated. This can be configured in your .gwt.xml file:</p>
<pre class="xml:nocontrols">  <set-property name="compiler.stackMode"
       value="emulated" />
  <set-configuration-property name="compiler.emulatedStack.recordLineNumbers"
       value="true"/>
  <set-configuration-property name="compiler.emulatedStack.recordFileNames"
       value="true"/>
</pre>
<p>Note, again, that this does increase the size of your Javascript bundle. For one application I worked on, I found that just turning on the emulatedStack increased the Javascript by 30%, and turning on emulatedStack plus line numbers increased it by 100% (i.e. doubled the size!). Depending on the performance requirements of your application, this may or may not be acceptable.</p>
<p>Finally, it's helpful to know that even with the obfuscated stack traces, there is still hope for hunting down mysterious exceptions. What seems like jibberish is just obfuscated code, and you can manually translate the obfuscated method names (e.g. "Jq", "Tm", or "Sm" from the above example) to the Java method names using the <a href="http://code.google.com/p/google-web-toolkit/wiki/WebModeExceptions">symbolMaps</a> file that GWT generates. If only there were a way to do this programmatically...</p>
<h3>6. Use the StackTraceDeobfuscator</h3>
<p>GWT provides a utility class called the <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.1/com/google/gwt/logging/server/StackTraceDeobfuscator.html">StackTraceDeobfuscator</a> which (as it advertises!) deobfuscates stack traces, translating the condensed, jibberish stack trace (like above) into a one that you would expect. If you're using GWT's remote logger, then it helpfully uses this by default, with one caveat: it knows <a href="http://stackoverflow.com/questions/7804434/finding-the-java-actual-stack-trace-from-a-javascript-stack-trace">where to find</a> the symbolMaps file. GWT places this in the "WEB-INF/deploy/your-app/symbolMaps" directory, and you can instruct the RemoteLoggerService to look there accordingly:</p>
<pre class="xml:nocontrols"><init-param>
  <param-name>symbolMaps</param-name>
  <param-value>your-app/symbolMaps</param-value</param-value>
</init-param>
</pre>
<p>You could also call the StackTraceDeobfuscator manually, if, for example, you had your own RPC service that handled exceptions in some custom way. I wrote a <a href="http://www.bennorthrop.com/code/gwt-stacktracedeobfuscator/MyStackTraceDeobfuscator.java">simple subclass</a> of the StackTraceDeobfuscator, and called it like this:</p>
<pre class="java:nocontrols">
<code data-language="java">public class LogServiceImpl extends LogService {
  public void logError(Throwable t, String stackTrace) {
    StackTraceElement[] sts = stackTraceDeobfuscator.deobfuscateStackTrace(t.getStackTrace());
    t.setStackTrace(sts);

    LOG.logError("An error happened", t);
  }
}
</code>
</pre>
<h3>7. Throw exceptions explicitly in RPC Services</h3>
<p>Now, to the server side (which, thankfully, is much less tricky!). Imagine you have a simple RPC service that throws a custom exception, MyRuntimeException, which extends from <a href="http://docs.oracle.com/javase/6/docs/api/java/lang/RuntimeException.html">RuntimeException</a>. For example:</p>
<pre class="java:nocontrols">
<code data-language="java">public class MyServiceImpl extends MyService {
  public void foo() {
    throw new MyRuntimeException();
  }
}
</code>
</pre>
<p>By Java's rules, there is no obligation that you explicitly declare (either in the impl or interface) that foo throws MyRuntimeException. For the sake of simplicity, you may choose not to, however you might be surprised then to find that when you catch this exception in your <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.4/com/google/gwt/user/client/rpc/AsyncCallback.html">AsyncCallback</a>...</p>
<pre class="java:nocontrols">
<code data-language="java">myService.foo(new AsyncCallback<Void>() {
  public void onSuccess(void v) {
  }

  public void onFailure(Throwable t) {
    if(t instanceof MyRuntimeException) {
      // do something
    }
  }
}
</code>
</pre>
<p>...the object t will not be an instance of MyRuntimeException, but rather an <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.4/com/google/gwt/user/server/rpc/UnexpectedException.html">UnexpectedException</a>. This is because GWT did not know to compile MyRuntimeException into Javascript, and so the client code does not know of this type. To remedy, make sure you explicitly throw MyRuntimeException in your service interface (but not in your Async interface!):</p>
<pre class="java:nocontrols">
<code data-language="java">public interface MyService {
  void foo() throws MyRuntimeException;
}
</code>
</pre>
<p>Note that if you threw some subclass of MyRuntimeException, the instanceof check <em>would</em> work, however be aware that GWT would then compile all concrete subclasses of MyRuntimeException, which could slow build time.</p>
<p>Whew...that's it. Please share any tips you have, or let me know if you see anything awry with what I've written. Thanks!</p>				]]>			</description>
			<pubDate>Mon, 11 Jun 2012 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2012/7-tips-for-exception-handling-in-gwt.php</guid>
		</item>
		<item>
			<title>Power Hour - an alternative to Pomodoro</title>
			<link>http://www.bennorthrop.com/Essays/2012/power-hour-an-alternative-to-pomodoro.php</link>
			<description>
				<![CDATA[				<p>I&#8217;m not a psychologist, but it seems to me like the science is in, and it doesn&#8217;t look good for <a href="http://en.wikipedia.org/wiki/Human_multitasking">multitasking</a>.  </p>

<p>The idea that the brain can do two things simultaneously has been <a href="http://www.brainrules.net/attention?scene=">myth busted</a>.  Instead, we&#8217;ve learned that we have just a serial processor, and although it may be deft enough to provide the illusion of multitasking, on the inside it&#8217;s just an <a href="http://en.wikipedia.org/wiki/Human_multitasking#The_brain.27s_role_in_multitasking">executive controller</a> quickly switching back and forth from one task to another.  </p>
<p>But is there anything wrong with an illusion, if the result is the same?    </p>
<p>Well, yes.  The problem is that there&#8217;s a cost to this context switching.  A big one.  For starters, studies have shown that we are actually <a href="http://www.dailymail.co.uk/health/article-1205669/Is-multi-tasking-bad-brain-Experts-reveal-hidden-perils-juggling-jobs.html" >less productive</a> overall while multitasking, and make significantly <a href="http://www.nytimes.com/2007/03/25/business/25multi.html?pagewanted=all">more mistakes</a>.  In addition, multitasking also <a href="http://news.stanford.edu/news/2009/august24/multitask-research-study-082409.html">inhibits learning</a>, <a href="http://news.bbc.co.uk/2/hi/uk_news/4471607.stm">lowers IQ</a>, and <a href="http://seattletimes.nwsource.com/pacificnw/2004/1128/cover.html">increases stress</a>.  And as though that wasn&#8217;t enough, it turns out the more we multitask, the <a href="http://www.pnas.org/content/early/2009/08/21/0903620106.abstract">worse we are</a> at it.  Whew.</p>
<p>Despite all we know about the problems and perils of multi-tasking, however, the possibility of unitasking in the modern software development organization looks bleaker than ever.  Cramped or open office environments increase the possibility for disruptions from our physical surroundings, and the ubiquity of social networking technology (e.g. email, text, instant message, Facebook, etc.) invite interruptions from beyond.  </p>
<p>What&#8217;s more, within the world of software development, there&#8217;s a strong trend toward <a href="http://en.wikipedia.org/wiki/Agile_software_development">agile techniques</a>, which value above almost all else <a href="http://www.agilemodeling.com/essays/communication.htm">communication</a> and <a href="http://www.infoq.com/news/2011/03/agile-feedback-loops">continuous feedback</a>.  More interruptions!</p>
<p>Now it might seem at this point like I&#8217;m a luddite, a social recluse, or (gasp!) a <a href="http://en.wikipedia.org/wiki/Waterfall_model">waterfall</a> advocate, but in fact it&#8217;s just the opposite.  I&#8217;ve seen first hand the benefits of both Agile processes and new tools for communication, it&#8217;s just that I think (in some environments more than others) we might take it too far.  Responsiveness is important, but as the science of multitasking shows, there&#8217;s such a thing as over-communication.  For the sake of our productivity, our sanity, and the quality of what we&#8217;re building, at some point we need to tune out the world, sink into a state of concentration, and get some freaking work done.  But how?  </p>
<h3>Pomodoro</h3>
<p>The time management practice of <a href="http://en.wikipedia.org/wiki/Pomodoro_Technique" >Pomodoro</a> seems to be getting <a href="http://www.summa-tech.com/blog/2011/10/04/micro-time-management-to-dos-and-to-donts/">more attention</a> lately, especially within the <a href="http://www.infoq.com/news/2009/09/Pomodoro">Agile community</a>.  The idea is simple: set a clock for 25 minutes and allow yourself to work on one task, uninterrupted.  At the end of the Pomodoro, you get a quick break, and then you start again.  If something pops up during the Pomodoro (an email from a colleague, a phone call from the product owner, etc.) you&#8217;re advised to record it and get back to it when the 25 minutes are up.  Sounds great, right?</p>
<p>In my experience, it&#8217;s not so easy.  If a business owner pays you a visit from 2 floors up about a bug in the application, he may not be happy when you ask him to wait 17 minutes until you&#8217;re done with your &#8220;Pomodoro&#8221;.  Basically, the world doesn&#8217;t hinge on your stop watch.  </p>
<p>Even if it did, without knowing when you start or stop the clock, it&#8217;s impossible for a colleague to know when it&#8217;s appropriate to interrupt and when it&#8217;s not.  Depending on the size/activity of a team, a half dozen interruptions (of different forms) are easily possible within a 25 minute span.  Just acknowledging these is enough to lose concentration.</p>
<p>Lastly, if each developer is on his own Pomodoro cycle, you could easily (albeit absurdly!) reach a deadlock.  Joe pings Bill during Bill&#8217;s Pomodoro, and so Bill defers till after, but when he does, Joe&#8217;s in the middle of his Pomodoro and defers as well, and so on.  Eventually someone&#8217;s Pomodoro has got to budge.</p>
<h3>Introducing Power Hour</h3>
<p>What&#8217;s needed is a shared Pomodoro, whereby the team understands when the clock starts and stops, and collectively agrees not to interrupt each other during that time.  This is exactly what my we&#8217;ve created on my current project, and we call it &#8220;Power Hour&#8221; (not to be confused with any bevarage-oriented games you may or may not have played in college).</p>
<p>So far it&#8217;s been simple and effective.  Each day we have two Power Hours, one at 10am and one at 2pm.  During those two hours we all go &#8220;heads-down&#8221;, and get work done.  If one of us has a question for another during that time, we wait till after Power Hour to ask it.  There are obvious exceptions (bugs in production, calls from directors, free food in the cafeteria, etc.), but for the most part the sanctity of the hour is respected (even, now, by others outside of the team).  </p>
<p>It may seem that this technique might thwart communication, but in practice it just consolidates it, often to the 15 minutes before and after a Power Hour.  If I need an answer to a question before I start my work, I know I&#8217;ll need to ask my colleague before Power Hour begins, and vice-versa.  This is healthy trade &#8211; rather than a work-day full of randomly distributed interruptions, discussions organically converge into concise bursts.  </p>
<p>Who knows if we&#8217;ll have the discipline to keep up our Power Hours, but for now they&#8217;ve been a big help in countering the pressures for multitasking.  I&#8217;d be interested to hear your strategies for getting quality work done, efficiently.  Please share!</p>				]]>			</description>
			<pubDate>Mon, 02 Apr 2012 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2012/power-hour-an-alternative-to-pomodoro.php</guid>
		</item>
		<item>
			<title>Usability Testing on Agile Projects (part 2)</title>
			<link>http://www.bennorthrop.com/Essays/2012/usability-testing-on-agile-projects-part-2.php</link>
			<description>
				<![CDATA[				 <p>In <a href="http://wwww.bennorthrop.com/Essays/2011/usability-testing-on-agile-projects-part-1.php">part 1</a> of this series, I discussed the benefits of usability testing on enterprise software projects and outlined a general approach for integrating the practice of usability testing into a typical Scrum project (see diagram below).  In this post, Iâ€™ll lay out a 3-step process for performing a <a href="http://en.wikipedia.org/wiki/Usability_testing">usability test</a> on an enterprise project, describe some recognized best practices, and highlight how it can can hook into the standard elements of Scrum (e.g. <a href="http://www.mountaingoatsoftware.com/scrum/release-burndown">burndown</a>, <a href="http://www.mountaingoatsoftware.com/scrum/product-backlog">backlog</a>, etc.).  Here we goâ€¦</p>
<p><br/></p>
<div align="center">
<a href="http://wwww.bennorthrop.com/Essays/2011/usability-testing-on-agile-projects-part-1.php" target="_blank"><img src="scrum_and_usability_testing-300x223.gif" alt="scrum_and_usability_testing" title="scrum_and_usability_testing" width="300" height="223" class="aligncenter size-medium wp-image-3874"/></a><br/>
(<a href="http://www.summa-tech.com/blog/wp-content/uploads/2011/11/scrum_and_usability_testing.gif"" target="_blank">click</a> to expand)
</div>
<h3>Step 1: Plan for the Test</h3>
<p>Preparation is the trickiest part of usability testing. If good users are not found, relevant tasks not defined, or environments not set-up, the results of the test will be specious at best, or non-existent at worst! It is crucial, therefore, to develop the right foundation for test: </p>
<p><b>Find the Users:</b> For the typical B2C web site, representative users can be found at any street corner or coffee shop. For many enterprise projects, however, users are not so easily located or accessed. Because users of enterprise software may have specific domain knowledge, work in different departments, or reside in different geographic offices, procuring access to them or aligning schedules can be a significant challenge. If possible, it is important to surmount these obstacles â€“ real users will give <a href="http://www.useit.com/alertbox/20030120.html" >more accurate feedback</a>, and will be generally more receptive of the system when it is eventually rolled out, becoming advocates of it rather than opponents to it. </p>
<p>When it is not possible to find real users, representative users (e.g. mapping to defined <a href="http://www.agilemodeling.com/artifacts/personas.htm">personas</a>), or even non-representative users, can be substituted with some success; many usability issues can be uncovered by users with no domain experience, a fresh set of eyes the most salient requirement. </p>
<p>It is <a href="http://www.useit.com/alertbox/20000319.html" >well documented</a> that usability testing requires no more than 4-6 users per round. Usability issues are typically universal and so are found early â€“ there are diminishing returns for testing with any more than 6 users (i.e. they all tell you about the same problems!). </p>
<p><br/></p>
<div align="center">
<a href="http://www.summa-tech.com/blog/2012/01/04/usability-testing-on-agile-projects-part-2/users/" rel="attachment wp-att-3904"><img src="users-300x179.jpg" alt="users" title="users" width="300" height="179" class="aligncenter size-medium wp-image-3904"/></a></div>
<p><b>Plan the Tasks:</b> Not every feature of an application can or should be usability tested. As noted above, it is important, therefore, to identify for usability testing only those features which are prominent, complex, or have a high cost of user error. Once these features are identified, a script of user tasks can be created. Note that tasks should clear, concise, and worded in a way that is <a href="http://www.uie.com/articles/usability_testing_mistakes/">independent of the design</a> of the application (e.g. not â€œclick â€˜add item to cartâ€™ and click the â€˜purchaseâ€™ buttonâ€ but rather â€œbuy a widgetâ€).  Lastly, it is important both to run through the script yourself, and also ask another team member to do the same, and ensure that the script takes no more than 15-30 minutes to execute (with the assumption that a user unfamiliar with the application could take 3x this long). </p>
<p><b>Write the Post-Test Questionnaire:</b> Depending on the application it may be useful to learn about not only the userâ€™s performance (i.e. can they use the system) but also their preference (i.e. do they like it). Surprisingly, it has been found that the two <a href="http://www.usability.gov/methods/test_refine/learnusa/index.html">do not always correlate</a> â€“ users may have problems using the application but say the like it, or use it fine but say they hate it. For this reason, it is important to supplement the observational data (i.e. notes from watching the user) with data from a post-test questionnaire. Note that demographic, qualitative, and quantitative data are important â€“ so ask both open-ended questions like â€œhow did you feel about XYZ?â€ and â€œon a scale of 1-5, was the system usable?â€. Lastly, the late usability expert <a href="http://en.wikipedia.org/wiki/Randy_Pausch">Randy Pausch</a> advocated always asking at least one question after a usability test: â€œwhat were the two worst things about the system?â€, guaranteeing that the user will be forced to shed light on at least two tangible usability flaws (and not try to avoid hurting your feelings). </p>
<p><b>Set up the Environment, Data, and Access:</b> Finally, a stable and perhaps isolated version of the system must be available for the test participants to use. In many cases this will be the normal QA environment, but depending on the frequency of builds or transiency of the data, this may or may not be adequate. If it is not, alternatives may be either to deploy the system on your local machine or to create a special, temporary environment specifically for usability testing. The feasibility of these options obviously depends on the complexity of the application and dependent sub-systems, serivces, or data stores â€“ a simple single web-app to single database may be easy to configure and deploy, whereas a complex system that leverages LDAP, multiple databases, an ERP, and a handful of external web-services would not be. </p>
<p>Additionally, for some usability test scripts, it will be necessary to have each user test with a fresh, pre-configured, non-confidential set of data (for example, maybe a user is asked to find the user with an outstanding balance, and so such a user must exist). If this is the case, a set of SQL set-up and tear-down scripts may be necessary, or perhaps just a script for manually re-creating the data via the user interface. In any case, it is imperative to understand the data dependencies for the test up-front, to ensure that tests go smoothly, and users find issues related to usability and not bad data conditions. </p>
<p>Lastly, in many cases the test subject will log in as a pre-configured, sample user, however in some cases it will be helpful for the user to log in as himself and see â€œhisâ€ data during the test. In this case, it is important to ensure the user has appropriate access control for the QA environment â€“ and itâ€™s not until he tries to log in that you discover that he doesnâ€™t have authorization. </p>
<h3>Step 2: Perform the Test</h3>
<p>If planning is done correctly, actually performing the usability test should be a snap â€“ your job is simply to make the subject feel comfortable, stand back, and watch what they do! Here are a few things to keep in mind. </p>
<p><b>Introduce Yourself and the Test:</b> When meeting the user, itâ€™s important to set a very informal, relaxed, and open atmosphere early, so that the user feels comfortable sharing how they feel about the system. To that end, be sure to mention the following simple points: </p>
<ul>
<li>It is the system that is being tested, not them.</li>
<li>The system has issues, but itâ€™s difficult for developers to see them because we are too close to the problem. This is why their help is so important.</li>
<li>Negative feedback is actually more helpful than positive. No feelings will be hurt if they are frustrated or donâ€™t like something.</li>
<li>Their help is greatly appreciated, and will contribute to a better product.</li>
<li>If they get stuck you can jump in and help, but otherwise youâ€™ll stay quiet and let them drive.</li>
</ul>
<p>After introductions, give them the test script and have them briefly skim the tasks. Convey to them that although the tasks should only take 30-45 minutes, they should feel comfortable taking their time. </p>
<p><b>Observe, Ask Questions, but Donâ€™t Help:</b> Once the user has begun, itâ€™s important to let them use the system as they wish, even if it means them navigating down false paths (the whole point is to see how they would use it if you werenâ€™t there!). As they complete the tasks, <a href="http://en.wikipedia.org/wiki/Think_aloud_protocol" >encourage them to talk</a>, and be sure to ask probing, but non-revealing, questions, like â€œI saw that you clicked the â€˜filterâ€™ button but were surprised with the result â€“ what did you expect would happen there?â€. If the user is hopelessly stuck, then it may be necessary to give them hints, but otherwise remain an observer.</p>
<p><b>Take Notes:</b> As the user completes the tasks, take copious notes of their actions, comments, and frustrations â€“ these notes will trigger your memory later and fuel the <i>Usability Observations</i> list that you assemble. Many would <a href="http://www.boxesandarrows.com/view/recording_screen_activity_during_usability_testing" >argue</a> that it is necessary to also video record usability test sessions, however, the benefit is rarely worth the cost in my opionion (even though it is relatively <a href="http://camstudio.org/">cheap</a>): project stakeholders seldom take the time to actually view a usability test video session, users may be apprehensive and less honest when being recorded, and the set-up and storage of the recordings can be frustrating and time-consuming.</p>
<h3>Step 3: Analyze the Results</h3>
<p>Once the tests have been completed, the data must be analyzed and then synthesized into a set of actionable recommendations. To do so, two artifacts can be created, an objective <i>Usability Observations List</i> and a subjective <i>Usability Analysis & Recommendation</i> document.</p>
<p><b>Create a Usability Observations list:</b> Go back through your notes, and record discrete usability issues that users encountered in a simple spreadsheet. The list should be objectively and tactfully worded, stating, for example, that the user â€œdid not know what the word â€˜invoiceâ€™ meantâ€ and not â€œâ€˜invoicesâ€™ should be called â€˜billsâ€™â€. Consensus should be noted for each item (e.g. â€œ3 out 6 usersâ€), and each should be classified either as a â€œusability bugâ€ (which would later be entered in an issue tracking system to be implemented during the current sprint) or as a â€œfeature requestâ€ (which would be added to the product backlog, to be prioritized for a future sprint). </p>
<p><b>Create a Usability Analysis & Recommendation document:</b> Finally, it will be helpful for project stakeholders to receive a high-level analysis of the usability test, summing up overall impression of the siteâ€™s usability (using both quantitative and qualitative data as useful), the areas of the system that were most and least usable, and a set of recommendations for future action (e.g. new features to the backlog, additional rounds of usability testing, etc.). This document may captured in a Wiki, stored in document control (e.g. SharePoint), or just sent via email. </p>
<p>Thatâ€™s it!  Again, Iâ€™d like to hear your thoughts on usability testing on enterprise projects.  Please share!</p>				]]>			</description>
			<pubDate>Tue, 17 Jan 2012 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2012/usability-testing-on-agile-projects-part-2.php</guid>
		</item>
		<item>
			<title>Usability Testing on Agile Projects (part 1)</title>
			<link>http://www.bennorthrop.com/Essays/2011/usability-testing-on-agile-projects-part-1.php</link>
			<description>
				<![CDATA[				<p>It is not enough that we deliver systems that are merely functional, they must also be usable. Paraphrasing from usability expert <a href="http://www.codinghorror.com/" >Jeff Attwood</a>, to the users of the system, â€œthe interface is the applicationâ€; it is their most visible window into our work. Whether we finish on time, on budget, or in scope can be immaterial if the final deliverable is frustrating or inefficient to use.</p>
<p>On most enterprise applications, in my experience, usability is promoted via a number of low-cost methods: following usability standards, deferring to user interface specialists, trusting our intuitions, or simply conferring with customers and business owners. And while these methods are sufficient in most cases, when usability is a high priority, there is simply no substitute for actually watching people, without interference, use the software we build. This is the practice of <a href="http://en.wikipedia.org/wiki/Usability_testing">usability testing</a>.</p>
<p>In particular, I believe that usability testing should be strongly considered on projects whereâ€¦ </p>
<ol>
<li>The user base of the system is <i>numerous, not technically-savvy, or external</i> to the customer. </il>
<li>The cost of <i>user error</i> is high (e.g. software for managing financial transactions, medical procedures, etc.) and features are complex.</il>
<li>The <i>UI framework</i> or paradigm is nascent or highly flexible (e.g. RIA, iPhone, etc.) and a consensus on usability patterns or best practices has not yet been reached.</il>
</ol>
<p>In addition to making our products easier to use, usability testing can also be of great benefit to us, the developers of the software, by improving our usability intuitions, educating us on the functional domain and application of the software we build, and re-enforcing for us that what we create has a tangible impact on real people. </p>
<p>In this post Iâ€™ll describe usability testing within <a href="http://en.wikipedia.org/wiki/Agile_management" >agile projects</a> from a project management perspective, describing how to estimate, prioritize, and â€œburn-downâ€ the usability test.  In a follow-on post, Iâ€™ll dig into the actual activity of usability testing, breaking down some best practices within the framework of a simple 3-step process: (1) plan for the test, (2) perform the test, and (3) analyze the results.  Letâ€™s get startedâ€¦</p>
<h3>Managing Usability Testing with Scrum</h3>
<p>Effective usability testing can be <a href="http://24ways.org/2006/fast-and-simple-usability-testing" >easy</a>, <a href="http://24ways.org/2006/fast-and-simple-usability-testing" >quick</a>, <a href="http://www.useit.com/papers/guerrilla_hci.html" >cheap</a>, and, as the diagram below shows, can fit seamlessly within the <a href="http://en.wikipedia.org/wiki/Scrum_(development)" >Scrum methodology</a>.  Here are some tips, given my experiences with usability testing on Agile projects, on how this can be achieved:</p>
<p><br/></p>
<div align="center">
<a href="scrum_and_usability_testing.gif" target="_blank"><img src="scrum_and_usability_testing-300x223.gif" alt="scrum_and_usability_testing" title="scrum_and_usability_testing" width="300" height="223" class="aligncenter size-medium wp-image-3874"/></a><br/>
(<a href="scrum_and_usability_testing.gif" target="_blank">click</a> to expand)
</div>
<p><b>Usability Test as Backlog Item:</b> Unlike other development best practices (like code reviews or unit testing), usability testing should, in my opinion, not be â€œbuilt-inâ€ as a part of normal development tasks, but rather should be treated as a separate <a href="http://www.mountaingoatsoftware.com/scrum/product-backlog" >backlog item</a> - given an estimate by the development team, a priority by the business owners, and is assigned to a sprint for completion. Unlike other backlog user stories or tasks, however, usability testing has the property that it is never truly â€œdoneâ€ - there are cases when (indeterminately) many rounds should be performed, and so the task of usability testing should never really be permanently plucked from the backlog.  </p>
<p><b>Estimation:</b>  Although the amount of time it takes to perform a usability test depends on many project factors (e.g. scope or complexity of the application, availability of users, etc.), in my experience (using the methodology to be laid out in the next post) effective usability testing can usually be completed with roughly 30 man-hours of work: 15 for the preparation, 10 for the test itself, and 5 for the analysis and communication of results. </p>
<p><b>Prioritization: </b> Oftentimes, even when usability testing should be performed (see above), business owners or other project stakeholders will still be reluctant or apprehensive to do so - especially when other methods (like just trusting intuitions) are cheaper and seem just as effective. It is important in these cases to stress that (a) <a href="http://www.useit.com/alertbox/20030825.html">usability is important</a>, (b) we are notoriously bad judges of what is usable (too technical, too close to the system, etc.) and (c) usability testing can be cheap and extremely fruitful. Further, it is crucial to note that the earlier in the lifecycle that usability issues are identified, the easier they are to resolve - for example, redesigning a systemâ€™s confusing navigation structure once it is in production can be extremely costly and risky. In the end, however, usability testing should be prioritized along side all other user stories on the backlog, and this prioritization should be driven by the product or business owner.</p>
<p><b>Usability Testing as a Burndown Task: </b> Once usability testing has been selected for inclusion in a sprint, it should be assigned to one developer (where in agile teams, â€œdeveloperâ€ can mean tester, programmer, UI designer, etc.). Note that all activities of usability testing (planning, testing, and analysis) should fit within one sprint, and the task should be â€œburned-downâ€ like any other development task. The practice of usability testing does not require an â€œexpertâ€. <a href="http://sensible.com/downloads/DMMTchapter09_for_personal_use_only.pdf" >Anyone is capable</a> of performing one, and in fact, should if given the opportunity - it can be a rewarding and broadening experience.</p>
<p><b>Incorporating Feedback: </b>  Once the usability test is performed, observations from the test will be analyzed and discussed (see next post), and eventually some consensus will be achieved regarding how the application should change to improve user experience or efficiency.  This feedback can flow back through the Scrum development process in one of two forms: either as (1) new <a href="http://en.wikipedia.org/wiki/User_story">user stories</a> added to the backlog (e.g. â€œas a customer, I want to be able to use wild cards in text searchesâ€) or, when improvements are simple, as (2) bugs managed by the defect tracking system (e.g. â€œerror messages should be red, not yellowâ€).  </p>
<p>As always, Iâ€™d be happy to hear about your experiences with usability testing on Agile projects.  How often do you usability test?  How do you track it from a project management perspective?  Please share! </p>
<p>Also, check back in a few weeks for <a href="http://www.bennorthrop.com/Essays/2012/usability-testing-on-agile-projects-part-2.php">part 2</a> where Iâ€™ll dig in to the actual practice of usability testing in more detail.  </p>				]]>			</description>
			<pubDate>Sun, 20 Nov 2011 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2011/usability-testing-on-agile-projects-part-1.php</guid>
		</item>
		<item>
			<title>Getting Past the Deciders</title>
			<link>http://www.bennorthrop.com/Essays/2011/decision-fatigue-and-software-development.php</link>
			<description>
				<![CDATA[				<p>As a developer in industry, you're almost never a lone wolf - you work within some team.  So when big, <a href="http://www.bennorthrop.com/Essays/2009/what_is_good_architecture.php">architecture-level</a> decisions need to be made, as much as you'd love to call the shots, you've got to get the consensus of the group.  For example...</p>

<p class="indentableSubtle">Imagine that some for some feature you're working, it could be implemented in a number of different ways, each with some impact to maintainability, performance, reusability, and development effort.  You probably have a strong sense for which path is best, having looked at the problem in detail, but it's not usually wise to do anything until others (e.g. managers, business owners, other developers, etc.) weigh in.  Until the decision is made, however, your task is blocked...and the sprint deadline looms.</p>

<p>In these cases, your job is to pop this decision up to the right group of people and facilitate the <b>best decision, quickly</b> so you can get back to work implementing the feature.  Pretty simple, right?  Just schedule a meeting, present the evidence, make your cogent argument, and they're bound to see the light.  Err...not always.</p>

<p>In my experiences, facilitating a big decision is one of the more precarious, but crucial, tasks of the  enterprise developer.  Even if you get the right people in the room to make the decision, the discussion is like walking a tight-rope - one wrong step and you fall into the pit of indecision, or worse the abyss of irrelevant pontification.  </p>

<p>So what can we do, as developers, to facilitate good, collective decisions?  One useful thing to consider a psychological phenomenon called <b>decision fatigue</b>, defined as:  </p>

<p class="indentableSubtle">
"the deteriorating quality of decisions made by an individual, after a long session of decision making" (<a href="http://en.wikipedia.org/wiki/Decision_fatigue">wikipedia</a>)
</p>

<p>On large enterprise projects, decision fatigue is (depressingly!) the standard mode of operating for many of us.  On any given day, we all must navigate and make decisions on dozens of complex, confusing, and frustrating issues, and this all takes mental energy.  The more choices we make, the more tired our brains get, and according to theory of decision fatigue, the more likely that we'll then make bad decisions, or defer the decision altogether (a decision in itself!)</p>

<p>Back to the original example then, how can you help the group not fall victim to decision fatigue, so they can come to a good decision and you can get back to your task? Here are a few strategies:</p>

<p class="indentable">
1. It's always best to <b>schedule morning meetings</b> for important decisions.  In a <a href="http://www.pnas.org/content/108/17/6889">recent study</a> on parole hearings in Israeli prisons, it was found that judges gave out parole 70 percent of the time when appeals were heard in the morning, and only 10 percent of the time when they were heard in the afternoon.  Essentially, after hours of listening to arguments, decision fatigue sets in, and judges would rather make no decision than the wrong decision.  Anecdotelly, this seems right - how many afternoon meetings end in the insanely-frustrating: "let's schedule another meeting!" - i.e. decision deferred.
</p>

<p class="indentable">
2. If decision fatigue is the result of making hard choices, then another answer is to <b>make choices easier</b> for the group.  One way to do this is to limit the solution set.  For example, a study discussed in the book <a href="http://www.amazon.com/Paradox-Choice-Why-More-Less/dp/0060005688">The Paradox of Choice</a> found that consumers were 10 times more likely to buy jam when they were presented with 6 flavors rather than 24 - in other words, too many options make decisions difficult.  As developers, when presenting decisions to the team, it's important therefore to frame the decision in the most "<a href="http://www.bennorthrop.com/Essays/2010/cognitive_fluency.php">cognitively fluent</a>" way possible, identifying ahead of time the salient trade-offs and simplifying to a manageable set of possible solutions.
</p>

<p class="indentable">
3. Lastly, if the first two tips don't work, <b>bring some candy</b> for the team.  Seriously.  In studies done by <a href="http://en.wikipedia.org/wiki/Roy_Baumeister">Roy F. Baumeister</a>, it was shown that sugar (specifically glucose) can effectively rejuvenate the brain from its decision fatigue, improving self control and the quality of decisions.  (Note that it's this effect that is partially responsible for the junk food you buy when grocery shopping on an empty stomach - your brain's out of fuel, and so it makes poor decisions.)
</p>

<p>
Obviously, there's plenty more to consider when helping a group come to a big decision, but being aware of decision fatigue might help.  As always, let me know what you think!  (and if you're interested in some of the research, <a href="http://www.nytimes.com/2011/08/21/magazine/do-you-suffer-from-decision-fatigue.html?pagewanted=all">here's</a> a great starting point.)
</p>				]]>			</description>
			<pubDate>Wed, 28 Sep 2011 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2011/decision-fatigue-and-software-development.php</guid>
		</item>
		<item>
			<title>A Room Full of Techies</title>
			<link>http://www.bennorthrop.com/Essays/2011/group-polarization-and-software-development.php</link>
			<description>
				<![CDATA[				<p>Imagine this scenario...</p>

<p class="indentableSubtle">
You and three friends stumble upon a great idea for a tech start-up.  Because you're all talented developers and there are no "business" people to constrain you, the only thing that separates you from monumental success is just building the darn application.  (seriously, it's a great idea).  So you decide to all sit in a room to brainstorm the initial architecture, then you'll divvy up the pieces and get started.  
</p>

<p>I've lived this scenario a handful times, and have seen it too many to count. </p>

<p>What you'd <b>expect</b> to happen is this: each developer will come to the table with a set of preferences on what the architecture should look like, based on their unique knowledge and experience.  All of these individual preferences would then be melded together, and the resulting architecture would represent some sensible compromise or average of the pre-discussion opinions.</p>

<p>What <b>actually</b> happens, however, is the exact opposite.  Instead of ideas being pushed toward some average, they get pushed to the extreme.  Cutting edge technologies, patterns, and approaches are chosen over relatively stable ones, and before you know it, you're programming the system in Clojure using a NoSQL database built using Gant, none of which anyone has any experience with.  Two months into development the team realizes that it spent most of its time learning the new technologies, and very little has been actually produced.  At this point the "window" has been missed, and everyone goes back to their old lives. </p>

<p>Some of what's going on here is the law of <a href="http://en.wikipedia.org/wiki/Group_polarization">group polarization</a>:</p>

<p class="indentableSubtle">"Members of a deliberationg group predictably move toward a more extreme point in the direction indicated by the members' predeliberation tendencies" (<a href="http://www.google.com/url?sa=t&source=web&cd=1&sqi=2&ved=0CBoQFjAA&url=http%3A%2F%2Fonlinelibrary.wiley.com%2Fdoi%2F10.1111%2F1467-9760.00148%2Fabstract&ei=kN0_Tv7ZJ66v0AG7l8m6Aw&usg=AFQjCNHBv4TTXKqRptwhgRw0SzbE11VeuQ">Sunstein</a>)</p>

<p>This phenomenon has been consistently replicated in a number of studies: conservatives meeting with other conservatives form more conservative beliefs, liberals more liberal, racists more racist, and so on.  It's why political parties hold conventions before elections, and why niche discussion boards on the internet end up going completely off the rails.  Like-minded peoples' preferences push toward the extreme.</p>

<p>The cause of this phenomenon seem to be two-fold:</p>

<p>First, people want to be <b>perceived favorably</b> by others, and so once they hear what others think, they adjust their opinion accordingly, to fit in with the group.  In terms of the original example, who wants to be the guy who suggests to write the new application in old, boring Java? Come on man!</p>

<p>Second,  people will share <b>evidence in support</b> of their opinions, which will further influence others in that direction (in which they are already leaning anyway).  Essentially, the argument pool will be limited to evidence on only one side, and so this preponderance of evidence will push everyone even further. </p>

<p>
Back to software development, group polarization happens often, potentially any time some relatively homogeneous faction (e.g. developers, managers, business owners, etc.) meets in isolation and makes decisions without input from others.  The antidote, as would be expected, is inviting diversity...which is one reason that Agile works so well, since it puts developers in the same room with business owners.   Although there may be disagreements, the resulting decision is typically some compromise.  </p>

<p>Anyway, I find it helpful to be on the lookout for group polarization.  And if I ever do a start-up again, I  may be that lame guy who suggests Java!</p>				]]>			</description>
			<pubDate>Mon, 08 Aug 2011 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2011/group-polarization-and-software-development.php</guid>
		</item>
		<item>
			<title>5 Tips for New Developers</title>
			<link>http://www.bennorthrop.com/Essays/2011/5-tips-for-new-developers.php</link>
			<description>
				<![CDATA[				<img src="kid-programmer.jpg" align="right" width="200" />
A couple weeks ago, I came across a good post, <a href="http://www.dzone.com/links/r/33_lessons_for_software_industry_novices.html">lessons for software industry novices</a>, and it inspired me to add a few more just for the heck of it... 

<h3>1. Don't check in code right before you go home</h3>
<p>It's 6:00, the [wife|kid|girlfriend|dog] is expecting you home in 30 minutes, and you just finished a really simple change.  There's no harm in just checking this code in now before you go, right?  DON'T DO IT!  I swear I have been burnt by this too many times to count.  If the build breaks or some bug pops up, you won't be there to resolve it...and every minute it goes unresolved you'll be losing good will with your fellow developers and testers.  Obviously I always run a local build before checking in, but now I go a step further and try to hold off on any  check-in if it's within an hour of me going home - better safe than sorry!
</p>

<h3>2. Batch your questions</h3>
<p>
As a new developer (or developer new to a team), you'll have loads of  questions.  This is good. Don't keep these to yourself, <i>however</i> don't ask them one-by-one as they pop into your brain.  Write them down on a list, and only when you can go no further, then ask the tech lead/analyst/business owner all of your questions in one batch.  People are almost always happy to help, but if you can limit the interruptions, it's always appreciated.
</p>

<h3>3. Stop complaining!</h3>
<p>
Yes, the  system you work on is insanely complex/convoluted, the business owners are totally irrational, and the development team dysfunctional.  Still...don't complain.  If enterprise software development was easy, businesses could (and would!) hire people a lot less smart than you, and pay a lot less money.  The fact that things are frustrating just means that talented developers are needed, and that we make a good living.  If things are so bad, then quit - there's always a market for good developers.  Otherwise, do what you were paid to do: make things better! 
</p>

<h3>4. Keep it Simple - Format Matters</h3>
<p>
We all know the virtues of writing clean, readable code, but we don't always apply this rule to the artifacts we produce: emails, documents, models, etc.  Spending time tuning/formatting these other products not only makes our ideas easily digestable by others, but  it makes our ideas <a href="http://www.bennorthrop.com/Essays/2010/cognitive_fluency.php">more persuasive</a> as well.  The minute it takes to tune an email for the people reading it is well worth it.  
</p>

<h3>5. Be Nice!</h3>
<p>
I'm not talking about "nice" in the traditional sense, but rather in a game-theoretic sense.  Many development activities can be boiled down to simple prisoner's dilemma situations: e.g. if we all comment our code we're better off, but individually it's more rational to be a free-rider and just take advantage of everyone else's comments (which is why it's sometimes <a href="http://www.bennorthrop.com/Home/Blog/2007_11_17_prisoners_dilemma.php">irrational to comment code</a>.  It's been <a href="http://www.google.com/url?sa=t&source=web&cd=1&ved=0CBUQFjAA&url=http%3A%2F%2Fwww.nonzero.org%2F&ei=8LU2TomyHM230AHVn53iCw&usg=AFQjCNEF5FTibCLFpt7GuknXXhCg511-jQ">found</a> that many people naturally play a tit-for-tat strategy, meaning if everyone else is "nice", they'll be nice too, but when someone free rides, they'll follow suit.  Given this, it's always good to play the nice strategy and help others (review code, unit test, etc.).  As soon as you don't, others won't either, and your development team can quickly turn to an every-man-for-themselves.
</p>				]]>			</description>
			<pubDate>Mon, 01 Aug 2011 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2011/5-tips-for-new-developers.php</guid>
		</item>
		<item>
			<title>Modeling Reference Data in the Application Tier</title>
			<link>http://www.bennorthrop.com/Essays/2011/reference-data-in-the-application-tier.php</link>
			<description>
				<![CDATA[				<p>In every enterprise application, there exists <a href="  http://www.information-management.com/issues/20060401/1051002-1.html?pg=2<br />
">reference data</a> - those simple entities that live on the periphery of your data model, and are used to classify your <a href="http://en.wikipedia.org/wiki/Master_data">master data</a>. We often know these entities by other names (depending on our point of view), for instance "lookup tables", "configuration data", etc. - examples being "State", "CustomerType", or "ProductType".</p>
<!--more-->
<p>Now there are some <a href="http://www.projectdmx.com/dbdesign/lookup.aspx">strong reasons</a> to model these entities in separate tables in your relational database, and there is generally not much debate here. Where things get a little tricky is when this reference data propagates up into the application tier. In my experience, developers employ a number of different strategies to solve this problem, and so in this post I'll define some of the more popular approaches and describe the pros and cons of each. As always, I'd love to hear your thoughts, so please share. Here goes...</p>
<h3>Types of Reference Data</h3>
<p>Let's first start with an example. Imagine your system has customers, and every customer has some loyalty level (e.g. "Gold", "Silver", etc."). The tables could be designed simply as follows:</p>
<p>Â </p>
<div align="center"><a href="http://www.summa-tech.com/blog/wp-content/uploads/2011/07/reference-data-erd1.gif" rel="attachment wp-att-3506"><img class="wp-float-center size-full wp-image-3506" style="width: 406px; height: 58px;" title="reference-data-erd1" src="reference-data-erd1.gif" alt="reference-data-erd1" width="406" height="58"></a></div>
<p>Â </p>
<p>...and the data in the LOYALTY_LEVEL table might be...</p>
<p>Â </p>
<table class="customTable" border="0" width="200" align="center">
<tbody>
<tr>
<td><strong>id</strong></td>
<td><strong>name</strong></td>
</tr>
<tr>
<td>G</td>
<td>Gold</td>
</tr>
<tr>
<td>S</td>
<td>Silver</td>
</tr>
<tr>
<td>B</td>
<td>Bronze</td>
</tr>
</tbody>
</table>
<p>Â </p>
<p>This is a pretty vanilla example, so it would be tempting to jump right in and translate this into the application tier, but before we do it's important to stop and ask a few questions first:</p>
<ol class="customList">
<li>Does the reference data need to be retrieved <strong>independent</strong> of the master data (e.g. display all loyalty levels in a drop-down, etc.)?</li>
<li>Are there <strong>other attributes</strong> beyond just the normal id-name pair? For example, "description", "abbreviation", or something with more business meaning like "percentage discount", etc.?</li>
<li>Do specific values need to be hard-coded into the <strong>business logic</strong>? For example, could there be logic <code>if (cust.loyaltyLevel == "Gold") { sendOvernightMail() } </code> ...or something similar?</li>
<li>Is the reference data at all <strong>dynamic</strong>? For example, could there be a new loyalty level at some point (e.g. "Diamond" or maybe "Coal"!)? Further, is this reference data <em>very</em> dynamic in that it could be added by a user via some UI, or would a new value be a configuration change?</li>
</ol>
<p>Now I can hear the objections already: "hey, not all of these types of 'reference data' are really reference data!". And that's actually the point. Oftentimes, in my experience, we fail to appreciate these four distinctions, and we shoe-horn all entities that even roughly resemble reference data into the same solution, to sometimes pernicious consequences. For example, we may treat States the same as Loyalty Levels in the application tier, even though the former is probably static, not used in business logic, and will only ever have two-attributes, while the latter could be the exact opposite.</p>
<p>To best understand how to design for different types of reference data, it's helpful to lay out a few common solutions...</p>
<h3>1. Flatten in Model Class</h3>
<p>An unsophisticated (but not uncommon) approach is to flatten the reference data in the containing model object. For example, the customer class could look like this:</p>
<pre class="java:nocontrols">
<code data-language="java"> public class Customer {
    private String name;
    private String loyaltyCode;
    private String loyaltyName;  // optional
  }
  </code>
</pre>
<p>Obviously this will work, until a new attribute needs to be added to a Loyalty Level (e.g. "description")...or Loyalty Codes need to be retrieved independent of Customers (e.g. to populate some drop-down), in which case you'll probably want to define a...</p>
<h3>2. Custom Class</h3>
<p>A custom LoyaltyLevel class could be created with the two attributes "code" and "name"...</p>
<pre class="java:nocontrols"><code data-language="java">  public class LoyaltyLevel {
    private String code;
    private String name;
  }
</code></pre>
<p>...and then composed within the Customer class:</p>
<pre class="java:nocontrols"><code data-language="java">  public class Customer {
    private String name;
    private LoyaltyLevel level;
  }
</code></pre>
<p>On the up side, the LoyaltyLevel class could be fetched independent of Customers (e.g. to populate a drop-down, etc.), and attributes could easily be added to the LoyaltyLevel class without adding unnecessary bloat to the Customer class.</p>
<p>The problem comes when you want to create some business logic that refers to some specific loyalty level. Using the example above, it's possible that some business rule should be written such that customers at the "Gold" level are treated in special manner.</p>
<pre class="java:nocontrols"><code data-language="java">  if("G".equals(customer.getLoyaltyLevel().getCode())) {
    sendOvernightMail();
  }
  else {
    sendViaHorseAndBuggy();
  }
</code></pre>
<p>Again, this works, but there are a few problems. First, the "code" attribute in LoyaltyLevel is not type-safe, since it's just a String in the LoyaltyLevel class, and so there's not guarantee that an invalid value (e.g. "X") couldn't creep in. Second, we're hard-coding the level, "G", into our business logic, and while this could be ameliorated with a simple String constant, again, this is not type-safe (and a general <a href="http://www.odi.ch/prog/design/newbies.php#40">anti-pattern</a>). And finally, it's very easy to forget to write bugs where "G" is compared with the LoyaltyLevel object itself and not it's String code. For example:</p>
<pre class="java:nocontrols"><code data-language="java">  if("G".equals(customer.getLoyaltyLevel()) { // forgot .getCode()!
    sendOvernightMail()
  }
</code></pre>
<p>In other words, if specific LoyaltyLevels are to be used in the business logic, it's much preferable to keep them typesafe in an...</p>
<h3>3. Enum</h3>
<p>A LoyaltyLevel enum could be created in the application tier:</p>
<pre class="java:nocontrols"><code data-language="java">  public enum LoyaltyLevel {
    Gold("G", "Gold"),
    Silver("S", "Silver"),
    Bronze("B", "Bronze");

    ...
  }
</code></pre>
<p>...and a type handler construct in your ORM tool (like <a href="http://weblog.dangertree.net/2007/09/23/mapping-java-5-enums-with-hibernate/">Hibernate's</a> or <a href="http://www.google.com/url?sa=t&source=web&cd=2&ved=0CCAQFjAB&url=http%3A%2F%2Fibatis.apache.org%2Fdocs%2Fjava%2Fuser%2Fcom%2Fibatis%2Fsqlmap%2Fclient%2Fextensions%2FTypeHandlerCallback.html&ei=opIpToy2O4TAtgea4qDXAg&usg=AFQjCNHaijd_54pjsYM3LisX06KJGEzpXA">IBatis</a>, etc.) can be used to easily load this into the Customer object on retrieval from the database:</p>
<pre class="java:nocontrols"><code data-language="java">  public class Customer {
    private String name;
    private LoyaltyLevel level;
  }
</code></pre>
<p>Voila! This solves our problems, right? LoyaltyLevels can be retrieved independent of Customers, new attributes can be easily added without affecting the master data, and specific instances can be easily (and type-safely) referred to in business logic (e.g. "LoyaltyLevel.Gold == cust.getLoyaltyLevel()").</p>
<p>Not so fast! What happens when the business wants to add a "Diamond" level? Or wants to get rid of their "Bronze" level and replace it with an "Aluminum"? In either case, both the enum <em>and</em> the database need to change (since both redundantly define the Loyalty Levels), which obviously necessitates a code/configuration change (i.e. not something that could happen via some UI). In cases where the reference data is very static, this may be fine, but if Loyalty Levels are to be added with any fluidity, encapsulating the different values in Enums won't work.</p>
<h3>Analysis and Recommendations</h3>
<p>So I've presented 3 solutions, and as the table below shows, each solution has its drawbacks. Things are less clear now than before! What gives?</p>
<p>Â </p>
<table class="customTable" border="0" align="center">
<tbody>
<tr>
<td>Â </td>
<td><strong>Independent?</strong></td>
<td><strong>+2 Attributes?</strong></td>
<td><strong>Business Logic?</strong></td>
<td><strong>Dynamic?</strong></td>
</tr>
<tr>
<td><strong>1. Flatten in Model Class</strong></td>
<td class="bad">Bad</td>
<td class="bad">Bad</td>
<td class="bad">Bad</td>
<td class="good">Good</td>
</tr>
<tr>
<td><strong>2. Custom Class</strong></td>
<td class="good">Good</td>
<td class="good">Good</td>
<td class="bad">Bad</td>
<td class="good">Good</td>
</tr>
<tr>
<td><strong>3. Enum</strong></td>
<td class="good">Good</td>
<td class="bad">Bad</td>
<td class="good">Good</td>
<td class="bad">Bad</td>
</tr>
</tbody>
</table>
<p>Â </p>
<p>In the end, is there an good answer? Well, I've found the following two heuristics to be helpful:</p>
<p>1. If the reference data is static, has few attributes, and is used in business logic, use an <strong>Enum</strong>. The redundancy of reference data defined both in both an enum and a table in the database is relatively harmless (since the data is static!), and worth the cost for gaining the benefit of type safety, clarity, and ease of use (in my opinion).</p>
<p>2. In all other cases, use a <strong>Custom Class</strong>. In cases where the business logic seems to reference a specific value, rather than hard-code (e.g. "G".equals(code)), try to refactor this such that the data makes the decision rather than the code. For example, in the example of Loyalty Levels and shipping methods, a new column added to the Loyalty Level table...</p>
<table class="customTable" border="0" width="300" align="center">
<tbody>
<tr>
<td><strong>id</strong></td>
<td><strong>name</strong></td>
<td><strong>ship_overnight</strong></td>
</tr>
<tr>
<td>G</td>
<td>Gold</td>
<td>true</td>
</tr>
<tr>
<td>S</td>
<td>Silver</td>
<td>false</td>
</tr>
<tr>
<td>B</td>
<td>Bronze</td>
<td>false</td>
</tr>
</tbody>
</table>
<p>...and this would effectively eliminate the dependency on a specific reference data value in the code and move it to the database.</p>
<p>3. If you absolutely need to hard-code the "code" values of the reference data for business logic, then do so with <strong>constants</strong> in one place and as close to the reference data class as possible (preferably in it). Do not sprinkle hard-coded values (e.g. "G", "S", etc.) around your business logic. (I know...duh!)</p>
<p>Anyway, I'd love to hear your thoughts. Am I missing something? How do you manage reference data in the application tier?</p>				]]>			</description>
			<pubDate>Mon, 25 Jul 2011 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2011/reference-data-in-the-application-tier.php</guid>
		</item>
		<item>
			<title>An Agile Dilemma - How to start the Sprint</title>
			<link>http://www.bennorthrop.com/Essays/2011/agile-dilemma-how-to-start-your-sprint.php</link>
			<description>
				<![CDATA[				<p>Imagine it's the first day of your 2-week <a href="http://scrummethodology.com/scrum-sprint/">sprint</a> (iteration, etc.), and you're eager to get started.  Your <a href="http://en.wikipedia.org/wiki/Burn_down_chart">burndown</a> (or task list, etc.) has just 4 tasks:</p>

<table border="1"  align="center" class="simpleTable" >
  <tr>
    <th align="left">Task</th>
    <th align="left">Estimate</th>
  </tr>
  <tr>
    <td>1. Implement "Order Status" screen.</td>
    <td>35 hours</td>
  </tr>
  <tr>
    <td>2. Print username in system logs.</td>
    <td>2 hours</td>
  </tr>
  <tr>
    <td>3. Investigate clustering in Tomcat.</td>
    <td>15 hours</td>
  </tr>
  <tr>
    <td>4. Upgrade to newest version of GWT.</td>
    <td>20 hours</td>
  </tr> 
</table>
<br/>
<p>
The question is, then, how do you get started?  What do you do on that first day?  You've committed to completing all the tasks, so does it matter?  Of course it does.  
</p>

<p>
Two simple approaches are...
</p>

<p class="indentable">
1. Start with the tasks that are <b>most fun</b>.  "Investigating clustering" sounds interesting, so start with that!  This makes for a more enjoyable sprint...at least for the first few days.
</p>

<p class="indentable">
2. Knock off the <b>low hanging fruit</b> first, and get some quick gratification at the beginning of the Sprint.  Just like some financial gurus say to pay off your lowest debts first, it's nice to build some confidence before you get to the tough stuff.  
</p>

<p>
Honestly, I find it really tough <i>not</i> to use these strategies - I just naturally want to do the fun tasks or quick-wins first...but having lived through more than a few failed sprints, I've quickly learned better.  
</p>

<p>
First, there are some tasks which other developers are depending on me for (e.g. "Upgrading GWT"), and so if I wait till the last few days to do this, I effectively hose my colleagues.  Second, there are times when I don't finish all of my tasks (gasp!) - maybe I had to call in sick one day, or requirements shifted, etc.  If I do the most fun tasks first, I may have left some high value tasks hanging.  
</p>
<p>
So here are some more disciplined approaches:   
</p>

<p class="indentable">
3. Start with the task that has the <b>most dependencies</b> on it (either within my own task list or for other developers).  This approach is the best for keeping you in the good graces of your team. 

</p>
<p class="indentable">
4. Find out from the business owners which tasks are the <b>highest value</b> and work from high value to low - that way if something doesn't get done, it will be less of a big deal.  For example, the "Order Status" screen might be crucial to the business, but "Upgrading to GWT" is not as big a priority.
</p>

<p class="indentable">
5. Dig into the task that is the <b>most complex</b> first, so you can identify and mitigate the biggest risks right away, and you'll have more time to address them during the sprint than if you waited to the end.    
</p>

<p>
Now each of the last three approaches (which can be blended, of course), are significantly more disciplined than the first two, but there's still a problem...
</p>
<p>
 Most developers (me included) typically like to work sequentially - complete a task, move on to the next one.  I find this more gratifying (and less stressful), but not very effective.  It's very possible that lingering within each of my tasks is some big gotcha, that needs time (i.e. calendar time, not hours of work) to be dealt with.  For example, maybe there's some question about the "Order Status" screen that needs to be posed to a business owner, and that business owner is booked solid till Thursday.  Or maybe investigating clustering requires the assistance of a sys admin, and he needs a week lead time.  If I don't identify these dependencies early, I could easily put myself in a position where I can't complete my tasks.  
</p>
<p>
Given this, I've found the most effective approach to starting the sprint is this...
</p>
<p class="indentable">
6. On the first 2 days, take a <b>spike</b> through each of my tasks (similar to the <a href="http://www.extremeprogramming.org/rules/spike.html">XP concept</a>), understand better the requirements, and pick out the tricky pieces that might require input from others.  This may require writing some code, but not much.   Once I have a good handle, at a conceptual level, of what each task entails, then I can use some blend of strategies 3, 4, and 5.  
</p>
<p>
The biggest drawback to this approach is that on those first two days, I find myself barely burning any work down - because most of what I'm doing is asking questions and planning.  After everything is in order though, I typically can roll smoothly through my work.
</p>
<p>
Anyway, what are your thoughts?  How do you start your sprint?
</p>

				]]>			</description>
			<pubDate>Mon, 18 Jul 2011 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2011/agile-dilemma-how-to-start-your-sprint.php</guid>
		</item>
		<item>
			<title>Developers - How do you manage your to-dos?</title>
			<link>http://www.bennorthrop.com/Essays/2011/developers-how-do-you-manage-to-dos.php</link>
			<description>
				<![CDATA[				<p>There are days when my brain is literally over-flowing with things I have to do, and around every corner lies something new.  </p>

<p>For example, in any given hour, I could easily receive one more email from project manager, phone call from business owner, chat request from developer, one-on-one drop-in from architect, build failure notification,  and bug submission.  And every single one of these would result in the same thing: <b>more work on my to do list</b>.  Now add these to my existing tasks for this sprint, and all I can say is "holy crap". </p>

<p>
I'm sure it's no different for anyone else doing the enterprise development thing, so my question then is this: <b>how the heck do you manage this all</b>?  Or more specifically, how do you remember all that you need to do?  And at any given point in time, how do you know you're doing the highest priority thing?
</p>

<img src="developer-todos.gif" align="right"/>
 
<p>
Thinking on this a bit, I know there's probably not much I can do about the  quantity or frequency of incoming to-dos - working in a team environment is just inherently chaotic and complex.  
</p>

<p>
My main frustration then is really just that there are <b>so many lists of to-dos</b> for developers: bug tracking systems, project management tools, IDEs (e.g. <font family="courier new">TODO</font>), post-it notes, etc.   When I want to know what I have to do, I either have to consult each these multiple to-do "bins" or just try to keep it all in my brain  (which just means I'm thrashing all day ).  
</p>

<p>
Basically, what I really need is a <b>single place</b> to track all my development related to-dos (ala <a href="http://www.davidco.com/about-gtd">GTD</a>).
</p>

<p>For a long time, I tried to do this <a href="http://www.summa-tech.com/blog/2009/06/17/take-note-take-notes/">old-school</a>: with a <b>simple, paper notebook</b>.  Every time I identified something new to do, I'd write it down.  And while this is great for visualizing the entire list...and there's nothing better than physically crossing something off...there were obvious short-comings: I didn't always have my notebook on me, I was constantly writing and re-copying lists, there was no way to search or prioritize items, and there was no notification feature (that I was aware of ;).  </p>

<p>
More recently, I moved everything to my <b>smart phone</b> into a program called <a href="http://www.rexwireless.com/individuals-tmx.php">ToDo Matrix</a> (good, but kind of over- priced).  This works better than paper (more structure, searchable, etc.), and I've been able to consolidate most of my to-dos into one master list, but I still have a problem with redundancy (i.e. some to-dos are in the Bug Tracker, some in Rally, etc....and I either have to make a duplicate to-do on my phone, or keep them where they are and just consult multiple lists).
</p>

<p>So does anyone out there have a good strategy for ordering the chaos of a mere mortal enterprise software developer?  How do <i>you</i> manage your to-dos?</p>
				]]>			</description>
			<pubDate>Thu, 07 Jul 2011 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2011/developers-how-do-you-manage-to-dos.php</guid>
		</item>
		<item>
			<title>A pattern for GWT code splitting</title>
			<link>http://www.bennorthrop.com/Essays/2011/a-pattern-for-gwt-code-splitting.php</link>
			<description>
				<![CDATA[				<p>When building <a href="http://www.bennorthrop.com/Essays/2011/structuring-gwt-modules-for-large-applications/">large applications</a> with GWT, <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideCodeSplitting.html">code splitting</a> is a must â€“ otherwise, the entire application (i.e. Javascript bundle) is downloaded in one chunk on the initial load of the application, which is a good recipe for frustrated users!  Fortunately, the folks at Google have made the code splitting <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideCodeSplitting.html#use" >mechanism</a> extremely simple, and have provided a really handy <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideCompileReport.html">tool</a> for analyzing and debugging to boot.  </p>
<p>Even still, implementing code splitting can be a bit tricky, especially deciding where in your framework to build it in.  There are some helpful constructs and patterns out there (e.g. <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/AsyncProxy.html" >AsyncProxy</a>, <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideCodeSplitting.html#patterns" >Async Provider</a>, etc.), but itâ€™s still not really clear if there is a definitive best practice for code splitting in large applications using GWT <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideMvpActivitiesAndPlaces.html" >MVP</a>.  Soâ€¦for the purpose of (hopefully!) sparking some conversation on this topic, hereâ€™s a solution we came up with on a recent project.  Please feel free to share your solutionsâ€¦or any thoughts/criticism you have.  Here goesâ€¦</p>
<h3>Scenario â€“ Application with multiple â€œSectionsâ€</h3>
<p>Imagine an application that has multiple distinct â€œsectionsâ€, where each section contains lots of â€œthingsâ€ (places, dialogs, widgets, etc.), and further that a â€œthingâ€ can only live in one section.  For example, consider a simple app with three sections â€œAâ€, â€œBâ€, and â€œCâ€. </p>
<p><br/></p>
<div align="center"><a href="http://www.summa-tech.com/blog/2011/05/03/a-pattern-for-gwt-code-splitting/simpleapp/" rel="attachment wp-att-3169"><img src="simpleapp.png" alt="simpleapp" title="simpleapp" width="350" class="aligncenter size-full wp-image-3169"/></a></div>
<p>Again, anything that is one section cannot be programmatically referenced by something in another section.  In other words, the package dependencies should look like this: </p>
<p><br/></p>
<div align="center">
<a href="http://www.summa-tech.com/blog/2011/05/03/a-pattern-for-gwt-code-splitting/packages-2/" rel="attachment wp-att-3290"><img src="packages.jpg" alt="packages" title="packages" width="439" height="116" class="aligncenter size-full wp-image-3290"/></a>
</div>
<p><br/></p>
<p>If an application can be segmented in this way, then the â€œsectionâ€ could be a good boundary line for code splitting â€“ in other words the application could be chunked in four pieces: main, A, B, and C.  When the user first loads the application, only the main chunk is downloaded.  When he navigates to any place within section A, for example, then all of section A is downloaded, and similarly for sections B and C.  </p>
<p>Now sections may not always be good split points (perhaps they are too big, or there are inherent, un-refactorable dependencies from one section to another), but if they are, hereâ€™s how it can workâ€¦</p>
<h3>Place Subclass</h3>
<p>Create a subclass of the GWT <a href="http://tbroyer.posterous.com/gwt-21-places">Place</a>, from which all places in the application are extended.  This base class has a reference to a custom enum â€œSectionâ€, which defines the different sections in the application (e.g. â€œAâ€, â€œBâ€, â€œCâ€).  In psuedo-code it looks like this (though note thereâ€™s a lot missing from the MyPlace class):</p>
<pre class="java:nocontrols">
<code data-language="java"> 
public enum Section { 
    A, B, C;
}

public class MyPlace extends Place { 
    private Section section;
    ...
}
</code>
</pre>
<p>Again, since all places have a section, the URL for a specific place might look something like â€œ#someplace:section=Aâ€.</p>
<p><br/></p>
<h3>Composite and Section ActivityMappers</h3>
<p>Now each section will have itâ€™s own <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.1/com/google/gwt/activity/shared/ActivityMapper.html" >ActivityMapper</a> (e.g. AActivityMapper, BActivityMapper, etc.) which instantiates the individual Activities within its section.  Splitting up into separate ActivityMappers like this ensures that there is no one master ActivityMapper that has dependencies to all Activities in all sections (thereby breaking the dependency arrows, and thus code splitting).  </p>
<p><br/><br/>
<a href="http://www.summa-tech.com/blog/2011/05/03/a-pattern-for-gwt-code-splitting/activitymapper/" rel="attachment wp-att-3225"><img src="activitymapper.jpg" alt="activitymapper" title="activitymapper" width="578" height="285" class="aligncenter size-full wp-image-3225"/></a></p>
<p>These section-based ActivityMappers are glued together using a new, custom â€œcompositeâ€ ActivityMapper, which, onPlaceChange, inspects the Section of the Place, and then delegates to the appropriate custom section-based ActivityMapper. </p>
<pre class="java:nocontrols">
<code data-language="java"> 
public class CompositeActivityMapper extends ActivityMapper { 
    private final HashMap<Section, ActivityMapper> mappers = 
               new HashMap<Section, ActivityMapper>();

    public Activity getActivity(Place place) { 
        MyPlace myPlace = (MyPlace) place;
        return mappers.get(myPlace.getSection()).getActivity(myPlace);
    }

    public void addActivityMapper(Section section, ActivityMapper activityMapper) { 
      mappers.put(section, activityMapper);
    }
}
</code>
</pre>
<p><br/></p>
<h3>Custom PlaceController</h3>
<p>Finally, and this is the crux (!), the <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.1/com/google/gwt/place/shared/PlaceController.html" >PlaceController</a> is sub-classed, and loads the appropriate sectionâ€™s ActivityMapper in the runAsync, thereby drawing the split-point boundary around the entire section.  Essentially, the first time the user navigates to any place within a given section, the PlaceController will load that section (i.e. send down that sectionâ€™s Javascript code bundle).</p>
<pre class="java:nocontrols">
<code data-language="java"> 
    public MyPlaceController extends PlaceController { 
   
        private CompositeActivityMapper compositeActivityMapper = new CompositeActivityMapper();

        private HashMap<Section, ActivityMapper> activityMappers = 
                  new HashMap<Section, ActivityMapper>();

        public MyPlaceController(CompositeActivityMapper compositeActivityMapper) { 
            this.compositeActivityMapper = compositeActivityMapper;
        }

        public void goTo(Place place) { 
            MyPlace myPlace = (MyPlace) place;

            switch (myPlace.getSection()) { 
                case A:
                    GWT.runAsync(new RunAsyncCallback() {
                        public void onSuccess() {
                            if(activityMappers.get(A) == null) { 
                                activityMappers.put(A, new AActivityMapper());
                                compositeActivityMapper.addActivityMapper(Section.A, activityMappers.get(A));
                            }
                            parentGoTo(myPlace);
                        }
                        public void onFailure(Throwable t) { 
                            // handle somehow
                        }
                    }
                    break;
                 case B:
                     ...
            }
        }

        public void parentGoTo(AdminPlace place) {
            super.goTo(place);
        }
    }
</code>
</pre>
<p><br/></p>
<h3>Conclusion and Caveats</h3>
<p>Obviously, this is a high-level description, but hopefully you get the idea.  Through the creation of a few custom infrastructure classes (e.g. Place, ActivityMapper, PlaceController, etc.), code splitting can be managed at a section level relatively seamlessly to the end developer â€“ i.e. as long as the developer doesnâ€™t break the dependency structure, it will work.  </p>
<p>Finally, here are a few quick caveats:</p>
<ul>
<li>The <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideCompileReport.html" >compile report</a> is an essential tool for understanding and managing dependencies for the purpose of effective code splitting.  <a href="http://www.clarkware.com/software/JDepend.html" >JDepend</a> is also a useful tool for just the dependency portion.</li>
<li>Obviously my post leaves some details (e.g. GIN, etc.) out, but they should be orthogonal.</li>
</ul>
<p>Anyway, Iâ€™d love to hear other strategies for code splitting in MVP-based GWT apps â€“ please share.  Thanks!</p>				]]>			</description>
			<pubDate>Tue, 03 May 2011 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2011/a-pattern-for-gwt-code-splitting.php</guid>
		</item>
		<item>
			<title>Structuring GWT modules for large applications</title>
			<link>http://www.bennorthrop.com/Essays/2011/structuring-gwt-modules-for-large-applications.php</link>
			<description>
				<![CDATA[				<p>When creating large web applications with <a href="https://web.archive.org/web/20160103115158/http://code.google.com/webtoolkit/">GWT</a>, it's not always clear how to get started. The most important (but most difficult!) question, I've found, is exactly how to structure the project - i.e. what justifies creating multiple <a href="https://web.archive.org/web/20160103115158/http://download.oracle.com/javaee/1.4/tutorial/doc/WebApp.html">web applications</a>, multiple GWT <a href="https://web.archive.org/web/20160103115158/http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html">modules</a>, multiple <a href="https://web.archive.org/web/20160103115158/http://google-web-toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/core/client/EntryPoint.html">EntryPoints</a>, or everything all in one. Although there is plenty of discussion out there (<a href="https://web.archive.org/web/20160103115158/http://turbomanage.wordpress.com/2009/11/19/tips-on-organizing-gwt-modules/">here</a>, <a href="https://web.archive.org/web/20160103115158/http://stackoverflow.com/questions/332285/large-apps-in-gwt-one-module-or-several">here</a>, <a href="https://web.archive.org/web/20160103115158/http://groups.google.com/group/google-web-toolkit/browse_thread/thread/00fb7f998f571869/a8ab8b03422f4aa1?pli=1">here</a>, and <a href="https://web.archive.org/web/20160103115158/http://markmail.org/message/ktyqkg2uiaazh74b">here</a>), the general consensus is still a little muddy. Like anything in our business, it seems the "right" answer is "it depends", and so in this post I hope to highlight a few of the factors in this decision.</p>

<h3>Example: Web apps, GWT Modules, and EntryPoints</h3>
<p>
It's probably best to start with a simple example. Imagine you already have some ecommerce site (you can decide what it is that you sell!), and now you need to build an internal application to manage your business. There are two "sections" to this site: (1) the Inventory UI through which Customer Service Reps can see what's in stock, and (2) the Orders UI through which they can track orders and through which the Shipping Manager can fulfill orders and send them out.
</p>

<p align="center"><img src="gwt-modules.png" /></p>

<p>
Note that there is some code that both the inventory and orders sections will need to share ("common" above) - for example, base classes, domain classes, helpful utilities, etc.
</p>

<p>
The question is how do you structure this application within GWT? Here are a few choices:
</p>

<ol>
  <li>Two WARs: have a separate web application for the inventory and orders sections, each sharing the common.jar file.</li>
  <li>Two EntryPoint modules: have one web application, but create separate GWT modules for common, inventory, and orders, where inventory and orders both have <a href="https://web.archive.org/web/20160103115158/http://google-web-toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/core/client/EntryPoint.html">EntryPoints</a> defined (see picture below).</li>
  <li>One EntryPoint module, three dependent modules: have one web application, but split each of the three pieces (common, inventory, and orders) into their own GWT modules, and then create one main GWT Module with an entry point which imports the others (see picture below).</li>
  <li>One big GWT module: have one web application and just one GWT module and one entry point.</li>
</ol>

<p>
Just to be clear, here's a picture of the GWT module organization in options 2 and 3:
</p>


<p align="center"><img src="gwt-modules-2.png" /></p>

<p>
This decision is pretty fundamental, and so it's best to get it right <a href="https://web.archive.org/web/20160103115158/http://www.bennorthrop.com/Home/Blog/2008_01_20_decision_tree.php">up-front</a> (or at least to try!). Here are some factors to consider:</p>

<h3>Download Time</h3>
<p>
GWT applications are not like more <a href="https://web.archive.org/web/20160103115158/http://en.wikipedia.org/wiki/Web_application">traditional</a> web applications. When the user first navigates to the site, he downloads the entire application (as a Javascript bundle), rather than downloading the HTML for each page incrementally as he navigates through. This means, all things being equal, the larger the application, the larger the Javascript bundle, and so the longer the initial load time of the application. The problem is, however, that if a user never accesses a whole section of the site (e.g. Shipping Managers never use Inventory), he still needs to wait for that portion of the Javascript to load. And if there are many unused sections in the site for a given user, this could mean a lot of wasted time.
</p>

<p>
At first blush, this may seem like a legitimate argument for either options 1 or 2 above (separate web applications or separate modules with entry points), especially if the different sections are sufficiently large. And while taking this approach and breaking things out could definitely solve your download latency issue, before you do this there are few caveats to first consider.
</p>

<p>
First, GWT 2.x has essentially solved this problem with <a href="https://web.archive.org/web/20160103115158/http://code.google.com/webtoolkit/doc/latest/DevGuideCodeSplitting.html">code-splitting</a>, a mechanism that allows you to partition your code, and only download portions as the user needs them, not all at once. (Note: structuring the dependencies to allow for effective code splitting can be tricky, so it is imperative that you think this through up-front). Second, Google is pretty <a href="https://web.archive.org/web/20160103115158/http://code.google.com/webtoolkit/doc/latest/DevGuideCompileReport.html">clever</a> in how it can boil down even a relatively big application into a small amount of Javascript, so unless the application is very large, this is usually not an issue. And lastly, the Javascript for the application is <a href="https://web.archive.org/web/20160103115158/http://code.google.com/webtoolkit/doc/latest/DevGuideCompilingAndDebugging.html">cached</a> on the client, so only the first visit to the app could potentially be slow.
</p>

<p>
Looking at option 3, the different modules provide good possible division lines along which to code split, however code splitting is equally possible with option 4 (one GWT module) as well. Google has some <a href="https://web.archive.org/web/20160103115158/http://code.google.com/webtoolkit/doc/latest/DevGuideCodeSplitting.html#patterns">helpful patterns</a> defined for code splitting, and there are a number of other good sources as well (like <a href="https://web.archive.org/web/20160103115158/http://jcheng.wordpress.com/2010/02/16/elegant-code-splitting-with-gwt/">here</a>).
</p>

<p>
Essentially, application download time, in and of itself, is probably not a solid reason for breaking an application into multiple applications (either WAR or entry point), however if navigation between sections is rare, then it may be justified, which leads me to my next point...
</p>

<h3>Navigation and URL</h3>
<p>
With GWT, one application is just one URL (e.g. http://www.foo.com/index.html), and different "pages" are just inner links (e.g. "index.html#my-orders"). It may be important (for usability, SEO, security, etc.), however, for different "sections" of the site to have different URLs (e.g. "/orders/index.html" and "/inventory/index.html") rather than just one with inner links (e.g. "index.html#section=orders" and"index.html#section=inventory").
</p>

<p>
A most obvious solution would be to split it into different web applications (option 1), but in many cases (including the example above), this won't work - e.g. the two sections may need to share an HTTP session, etc.
</p>

<p>
Creating different GWT entry point modules (option 2) could solve this issue as well - there would be only one web application this time, but each module would be accessible via a different URL. The downside here, however, is navigating between these modules (e.g. inventory-to-orders or orders-to-inventory). First, the normal mechanism for navigating in <a href="https://web.archive.org/web/20160103115158/http://code.google.com/webtoolkit/doc/2.1/ReleaseNotes.html">GWT 2.1</a> (i.e. placeController.goTo()) only works within modules, and so it'll be necessary to "hard-code" the module that you are navigating to in the <a href="https://web.archive.org/web/20160103115158/http://stackoverflow.com/questions/3250976/navigate-between-gwt-modules">navigation code</a> (e.g. Window.Location.assign()). Second, client-side state <a href="https://web.archive.org/web/20160103115158/http://stackoverflow.com/questions/4818900/maintaining-state-between-multiple-entries-to-same-gwt-module">cannot be shared</a> between GWT modules with different entry points, so if a module needs to know about something from another module, it'll have to go to the server.
</p>

<p>
These disadvantages may be acceptable, especially if the different sections are accessed by mutually exclusive sets of users, and so cross-section navigation is rare. Otherwise, keeping things together, either in one entry point but multiple GWT modules (option 3) or one module altogether (option 4), will be necessary, and you'll just have to live with the new, <a href="https://web.archive.org/web/20160103115158/http://www.tbray.org/ongoing/When/201x/2011/02/09/Hash-Blecch">AJAXy-style</a> URLs.
</p>

<h3>Compile Time</h3>

<p>
As you know, in GWT applications, Java code gets compiled into Javascript. This compilation can take a fair amount of time for larger applications (even when compiling for just one browser), and slow builds make developers less productive. Not good. Of course GWT is smart enough to only compile what's changed, and most times developers are working within the <a href="https://web.archive.org/web/20160103115158/http://code.google.com/webtoolkit/doc/2.1/DevGuideCompilingAndDebugging.html">hosted mode</a> which doesn't necessitate a manual build, but even still, in a team environment "clean" builds are sometimes justified, and if these are slow it can significantly disrupt a developer's <a href="https://web.archive.org/web/20160103115158/http://en.wikipedia.org/wiki/Flow_(psychology)">flow</a>.
</p>

<p>
Surprisingly, segmenting applications into multiple entry point GWT modules (option 2) can often do more harm than good, especially in the case where the shared code is large. For each entry point module, GWT re-compiles everything it needs, so if there are two modules, "orders" and "inventory", and they both share "common", then "common" will be compiled twice (note: this is true even if common is a separate project and has already been compiled into a common.jar - i.e. the JAR contains no Javascript!). In this case, segmenting into multiple entry point modules would therefore significantly hurt build time, not help.
</p>

<p>
If the application is significantly large, then finding a way to speed build times, outside of the well established <a href="https://web.archive.org/web/20160103115158/http://stackoverflow.com/questions/1011863/how-do-i-speed-up-the-gwt-compiler">configurations/optimizations</a>, might still be necessary. Segmenting into separate GWT modules with one entry point (option 3), allows for a possible work-around. If developers typically work within only one functional module at a time (e.g. orders or inventory), it's possible for them to comment out (in their local environment only!) the references (e.g. imports in gwt.xml or code references, etc.) to the other un-used functional modules, thereby bypassing the GWT compile for these unnecessary modules in their local build. Basically, the idea is, using the example above, don't make the developer of the Orders section compile the Inventory section code when he'll only ever be working within Orders.
</p>

<p>
Of course developers have to remember not to check these files in, and of course the main build (e.g. Hudson, etc.) will build everything (e.g. Orders plus Inventory) and so will take the normal amount of time, but at least locally things would be faster. (Note: this is a trick we've used on projects with success, but I haven't heard others mention it - I'd love to hear about your tricks...or if you see a flaw in this approach).
</p>

<h3>Maintainability and Reusability</h3>

<p>
From a maintainability and reusability perspective, creating one monolithic application is a well-known path to a <a href="https://web.archive.org/web/20160103115158/http://www.laputan.org/mud/">big ball of mud</a>. If different teams of developers work on different sections, or if different pieces of the application may be re-used in the future by other applications, then modularizing in some way will be helpful (options 1, 2 or 3). In some cases this may mean creating one share-able set of client code (e.g. common), or possibly many (infrastructure, domain model, etc.) - depending on the expectation for re-use. Again, in general, for an enterprise-scale GWT application, it's important to put some thought into <a href="https://web.archive.org/web/20160103115158/http://discuss.joelonsoftware.com/default.asp?design.4.361674.6">dependency organization</a>, using either projects, web applications, GWT modules, or <a href="https://web.archive.org/web/20160103115158/http://en.wikipedia.org/wiki/Java_package">packages</a> as a unit of structure.
</p>

<h3>Conclusion</h3>

<p>
As I mentioned at the start, the "right" approach to structuring a large-scale GWT application completely depends on the requirements of the project. I hope this post has at least shed some light on a few of the factors that are important to consider, but I know I've only scratched the surface...so please let me know about your experiences, or what I might be missing!
</p>				]]>			</description>
			<pubDate>Tue, 22 Feb 2011 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2011/structuring-gwt-modules-for-large-applications.php</guid>
		</item>
		<item>
			<title>Parallel asynchronous calls in GWT</title>
			<link>http://www.bennorthrop.com/Essays/2010/parallel-asynchronous-calls-in-gwt.php</link>
			<description>
				<![CDATA[				<p>The <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideServerCommunication.html#DevGuidePlumbingDiagram">asynchronous nature</a> of <a href="http://code.google.com/webtoolkit/">GWT</a> makes for more powerful and <a href="href="http://www.bennorthrop.com/Essays/2010/usability-ria-and-gwt.php"">usable</a> web applications, but as a developer, it can take a little while to <a href="http://dushmis.wordpress.com/2010/09/07/gwt-getting-used-to-asynchronous-calls/">get used to</a>. Here's one example: imagine a scenario where some client-side class needs to call two service operations before it can do something. Simple, right? In a synchronous world, it would be:</p>
<!--more-->
<pre class="java:nocontrols"><code data-language="java">public void someMethod() {
  Service someSerive = new SomeService();
  String str1 = someService.foo();
  String str2 = someService.bar();
  doSomething(str1, str2);
}</code></pre>
<p>In GWT, things are necessarily a little trickier. Using the standard <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideServerCommunication.html#DevGuidePlumbingDiagram">RPC plumbing</a>, calls from the client to a remote service are handled asynchronously, via GWT's <a href="http://google-web-toolkit.googlecode.com/svn/javadoc/2.1/com/google/gwt/user/client/rpc/AsyncCallback.html">AsyncCallback</a> mechanism. For example:</p>
<pre class="java:nocontrols"><code data-language="java">someService.foo(new AysncCallback() {
    public void onFailure(Throwable caught) {}

    public void onSuccess(final String str1) {
      // do something here;
    }
});</code></pre>
<p>This is relatively straight-forward. If we wanted to make two calls to some service, however, then do something after <em>both</em> have completed, our first instinct might be to just <strong>chain the service calls</strong> - e.g. when one service completes, call the second:</p>
<pre class="java:nocontrols"><code data-language="java">public void someGwtClientSideMethod() {
  SomeServiceAsync someService = GWT.create(SomeService.class);
  someService.foo(new AsyncCallback<String>() { 

    public void onFailure(Throwable caught) {}

    public void onSuccess(final String str1) {
      service.bar(new AsyncCallback<String>() { 

        public void onFailure(Throwable caught) {}

        public void onSuccess(String str2) {
          doSomething(str1, str2);
        }
      });
    });
  }</code></pre>
<p>While this works, it's not ideal. First, it's really ugly...and this is just for a case with 2 chained async calls - imagine if you had 3 or 4! Second, it's slower than it needs to be, since the calls are made serially rather than in parallel.</p>
<p>One obvious solution is to just <strong>combine the two service operations</strong> into one (an argument for this <a href="http://stackoverflow.com/questions/2993085/clean-way-in-gwt-java-to-wait-for-multiple-asynchronous-events-to-finish">here</a>) - only one call is made to the server, and you don't have to bother with the ugly nesting:</p>
<pre class="java:nocontrols"><code data-language="java">public void someGwtClientSideMethod() {
  SomeServiceAsync someService = GWT.create(SomeService.class);
  someService.fooAndBar(new AsyncCallback<FooBarResult>() { 

    public void onFailure(Throwable caught) {}

    public void onSuccess(final FooBarResult fbr) {
      doSomething(fbr.getFooResult(), fbr.getBarResult());
    }
  });
}</code></pre>
<p>This is better, but unfortunately combining service operations like this isn't always possible (or practical). Services may not be under your control...and even if they are, it's a lot of work to aggregate operations, and could result in a pretty complex/messy service if there are many such combinations.</p>
<p>Another possible solution would be to <strong>make the calls in parallel</strong>, and then only doSomething() when both service calls return. I developed two classes, <a href="http://www.bennorthrop.com/code/gwt-parallel-async/ParallelCallback.java">ParallelCallback</a> and <a href="http://www.bennorthrop.com/code/gwt-parallel-async/ParentCallback.java">ParentCallback</a>, for this exact purpose. Using these, the code in the client would look like this:</p>
<pre class="java:nocontrols">
<code data-language="java">public void someGwtClientSideMethod() {
  SomeServiceAsync someService = GWT.create(SomeService.class);
  ParallelCallback fooCallback = new ParallelCallback();
  ParallelCallback barCallback = new ParallelCallback();
  ParentCallback parent = new ParentCallback(fooCallback, barCallback) {
    public void handleSuccess() {
      doSomething(getCallbackData(0), getCallbackData(1));
    }
  };
  someService.foo(fooCallback);
  someService.bar(barCallback);
}</code></pre>
<p>Without getting too mired in the implementation guts, essentially each service method has its own ParallelCallback, which is registered with a ParentCallback. When the service has completed, the ParallelCallback then informs the parent it's done, and when the parent has heard back from each of is children, it calls its own handleSuccess() method, overridden and implemented by you. Return data from the individual service ParallelCallbacks can be extracted using the getCallbackData() method.</p>
<p>While this solution definitely still has some conceptual load, it eliminates the double-AsyncCallback-nesting, so seems a little simpler (to me!) than the chaining solution above. Also, as mentioned, RPC calls are made in parallel, so the overall <a href="http://en.wikipedia.org/wiki/Latency_(engineering)">latency</a> should be less.</p>
<p>Anyway, the code is available <a href="http://www.bennorthrop.com/code/gwt-parallel-async/ParallelCallback.java">here</a> and <a href="http://www.bennorthrop.com/code/gwt-parallel-async/ParentCallback.java">here</a> if you're interested. Let me know what you think, or if you've found another better way to solve this issue.</p>
<p><em>Note: this issue was <a href="http://stackoverflow.com/questions/2993085/clean-way-in-gwt-java-to-wait-for-multiple-asynchronous-events-to-finish">documented on StackOverflow</a>, and there are some good insights there as well (like check out <a href="http://code.google.com/p/gwt-dispatch/">gwt-dispatch</a> for one).</em></p>				]]>			</description>
			<pubDate>Mon, 29 Nov 2010 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2010/parallel-asynchronous-calls-in-gwt.php</guid>
		</item>
		<item>
			<title>Beyond Role-Based Access Control</title>
			<link>http://www.bennorthrop.com/Essays/2010/beyond-role-based-access-control.php</link>
			<description>
				<![CDATA[				<p>
When we think about <a href="http://en.wikipedia.org/wiki/Authorization">authorization</a>, we often think users, roles, and permissions.  Essentially, what a user can do in a system usually boils down to a simple formula:</p>

<div align="left" style="margin: 15px 0px 15px 80px">
  John is in Role X<br />
  Role X has Permission Y<br />
  ---------------------
  <br />
  John has Permission Y
  </div>

<p>And while this <a href="http://en.wikipedia.org/wiki/Role-based_access_control">role-based model</a> is effective, intuitive, and easy to implement, unfortunately, in most enterprise applications, it isn't enough - there are some portion of authorization requirements that can't be neatly codified in simple user-role-permission relationships.</p>

<p>In this post, I'd like to take a stab at defining some of the tricky (but common) authorization requirements that stretch the boundaries of basic role-based access control.  My hope is that by identifying (and putting a name to!) these different types of authorization rules, we'll be in a better position to determine the authorization solution that best fits our needs - whether it's a simple role-based approach or a complex policy engine (e.g <a href="http://www.oracle.com/technetwork/middleware/oes/index.html" >Oracle Entitlements Server</a>, <a href="http://www.cisco.com/en/US/products/ps9519/Products_Sub_Category_Home.html" >Cisco's Policy Manager</a>, etc.). </p>

<p>Ok, here goes:</p>
<div style="margin: 0px 0px 0px 20px">
<ul>
<li><a href="#SubjectAttributes">Subject Attributes</a></li>
<li><a href="#ObjectAttributes">Object Attributes</a></li>
<li><a href="#Row-levelFilters">Row-level Filters</a></li>
<li><a href="#Column-levelFilters">Column-level Filters</a></li>
<li><a href="#UserInterfaceHideShow">User Interface Hide/Show</a></li>
<li><a href="#DateTime">Date/Time</a></li>
<li><a href="#Expiration">Expiration</a></li>
<li><a href="#Delegation">Delegation</a></li>
<li><a href="#Hierarchies and Inheritance">Hierarchies and Inheritance</a></li>
<li><a href="#Impersonation">Impersonation</a></li>
</ul>
</div>
<p><br/></p>
<p><b>Subject Attributes</b><br />
Beyond roles, authorization rules often needs to consider some attribute of the person to determine whether they have access (see <a href="http://en.wikipedia.org/wiki/XACML" >ABAC</a>).  For example, if the requirement is: "only customers in the Pittsburgh region can approve a document", then a customer's region would be a relevant subject attribute to the authorization rule. </p>

<p>Attributes can be one-dimensional, in which case they can easily be encoded as simple roles (e.g. a user from the "Pittsburgh" region could be put in a "Pittsburgh" role).  When multiple attributes come into play, however, things get tricky.  For example, if both "region" and "customer priority" are relevant attributes, then encoding these in terms of roles would yield a messy combinatorial cross-product:</p>
<div align="left" style="margin: 15px 0px 15px 100px;">
Pittsburgh-SilverCustomer-Role<br />
Pittsburgh-GoldCustomer-Role<br />
Pittsburgh-PlatinumCustomer-Role<br />
Cleveland-GoldCustomer-Role<br />

</div>
<p>This obviously gets untenable from an administration perspective - i.e. what happens when we add a new region?  Or a new attribute?  For this reason, subject attributes typically need to be managed outside of roles.</p>

<h3>Object Attributes</h3>
On the flip side, attributes of the object of an action can also be relevant to an authorization decision.  For example, if the requirement is "a customer can only view his own bill", the system would need to verify that the object being acted upon (the bill) belongs to the subject (the customer).  Roles won't even come close to helping you with this type requirement!</p>
<div align="center" style="margin: 15px 0px 15px 0px;">
<img src="authorization-object-attributes.png" width="301" height="245" align="center" /><
</div>

<p>To make things more complicated, sometimes object attributes and subject attributes need to correlate - for example "only customer service reps from the Pittsburgh region can remove charges from customers from Pittsburgh" (see above).  In this case, the subject attribute (customer service rep's region) needs to match the object attribute (customer's region).</p>
<p><b>Row-level Filters</b><br />
Some authorization rules transcend binary permit/deny decisions; they instead state that results of a request be filtered to only those rows a user is authorized to view.  For example, perhaps a doctor querying a patient database should only be shown those patients for whom he's had contact, and hide the others.  Or "users from San Francisco  can only view customers from San Francisco".  I touched on this distinction between access control and filtering a bit more in a <a href="http://www.bennorthrop.com/Essays/2010/the-problems-of-decentralized-authorization.php" >previous post</a>.  </p>

<h3>Column-level Filters</h3>
Similarly, it can be necessary to restrict a specific column (or field) for certain users.  For example, it may be the case that customer service reps may <i>not</i> view a customer's SSN, but a manager may.  </p>

<p><b>User Interface Show/Hide</b><br />
Protecting an action by itself is sometimes not enough - we often want to prevent a user from trying to invoke it altogether.  For example, if a user doesn't have access to delete an account, then a "delete" button shouldn't be displayed on the UI.  This is something that , as developers, we often forget - we assume that  by protecting the service boundaries (urls, service operations, etc.) we've done enough, until we talk to users and they ask "if I'm not able to delete an account, why do you even give me the option?".  Ugh.  </p>

<p>To make matters more difficult, the logic that protects the action should ideally be the same logic that controls whether the button is shown or hidden - duplicating the logic in the client and server layers would be sub-optimal.  </p>
<p align="center"><img src="authorization-ui.png" alt="authz-ui" title="authz-ui" width="367" height="188" class="aligncenter size-full wp-image-2295" /></p>

<p><b>Date/Time</b><br />
Resources or actions can also be restricted based on the date or time - for example, "users can only submit requests during business hours of 8am-6pm" or "users can only approve documents after the 15th of the month". </p>
<p><b>Expiration</b><br />

There are times when a permission for a user should expire after some period of time - for example, "Joe has the permission to do X, but only for the next week".  These are similar to date/time rules, but subtly different.</p>
<p><b>Delegation</b><br />

Similarly, it is sometimes necessary to transfer one user's permissions to another.  For example, "Bob will be gone on vacation for 3 weeks, so delegate all his permissions to Ed".  In a simple role-based model, this is relatively trivial - just copy roles from Bob to Ed.  When using attributes, however, it can get a little trickier.  </p>
<p><b>Hierarchies and Inheritance</b><br />
For easier administration, roles can be organized in hierarchies, such that the permissions of a parent role are inherited by a child role - e.g. "a super admin can do everything that an admin can do, plus X, Y, and Z". Similarly, resources can also be organized hierarchically, e.g. "the admin can access any page under /admin/".</p>
<p><b>Impersonation</b><br />
In some cases, it's imperative for one user to enter a a system as another - similar to the "sudo" command.  For example, it might be helpful for a customer service rep to be able to log in as a customer, in order to see exactly what the customer sees, and help debug problems.  To complicate things, the customer service rep might only be able to view while logged in as the student, but not update any data.</p>
<h3>Conclusion</h3>
<p>As you can see, authorization rules come in a variety of flavors, and it's important to understand which your business needs, so that you can design/implement an appropriate solution.  Implementing an ill-suited authorization framework, or as is more common, just implementing authorization logic as custom application code, will be a <a href="http://www.bennorthrop.com/Essays/2010/the-problems-of-decentralized-authorization.php" >big problem</a> later on in terms of complex, unmaintainable code, difficult administration/provisioning, and incomplete auditing and reporting.</p>				]]>			</description>
			<pubDate>Fri, 01 Oct 2010 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2010/beyond-role-based-access-control.php</guid>
		</item>
		<item>
			<title>The Problems of Decentralized Authorization</title>
			<link>http://www.bennorthrop.com/Essays/2010/the-problems-of-decentralized-authorization.php</link>
			<description>
				<![CDATA[				<p>In a <a href="http://www.bennorthrop.com/Essays/2009/soa-and-authorization-part-1-whats-so-hard-about-it-anyway.php">previous post</a>, I laid some of the conceptual groundwork for authorization in the <a href="http://www.bennorthrop.com/Essays/2009/soa-and-the-n-plus-one-selects-problem.php">tricky world of SOA</a>. Now, a year older and a year wiser (I hope!), I'd like to swing back around to the topic of authorization, but broaden the scope a bit - talking not just about authorization and SOA, but about authorization and the whole enterprise "ecosystem" (services, applications, user interfaces, etc.).</p>

<p>In this post I'd like to describe the decentralized, "every man for themselves" model of authorization that is most common in organizations, and the problems inherent. In later posts I hope to touch on some possible paths out of this chaos - the <a href="https://web.archive.org/web/20150721205923/http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xacml">XACML</a> standard, <a href="https://web.archive.org/web/20150721205923/http://www.networkworld.com/newsletters/techexec/2007/0312techexec1.html">entitlement management</a>, and attribute services. Here goes...</p>

<h3>The Authorization Status Quo</h3>

<p>In any decent-sized organization, there exists a number of different systems that a given user may interact with - think HR, CRM, financial apps, knowledge management portals, ERPs, etc.. While these systems may differ along any number number of dimensions (size, technology, hosting model, etc.), each will inevitably share the common feature of authorization - in other words, each must define some rules for determining what a user can and cannot do within.</p>

<p>The problem is that while each system must "do" authorization, the way in which they actually do it can differ greatly. One system may take a simple <a href="https://web.archive.org/web/20150721205923/http://en.wikipedia.org/wiki/Role-based_access_control">role-based</a> approach leveraging <a href="https://web.archive.org/web/20150721205923/http://en.wikipedia.org/wiki/LDAP">LDAP</a> groups, a second may use an <a href="https://web.archive.org/web/20150721205923/http://en.wikipedia.org/wiki/Access_control_list">access control list</a> tying permissions directly to user IDs, and a third may just use some internal database connecting users to roles to permissions. Essentially, authorization in the enterprise is often a wild west - there are no laws; systems do as they do, with no connection between them in terms of either approach (RBAC, <a href="https://web.archive.org/web/20150721205923/http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=04032153">ABAC</a>, etc.), tools (e.g. JAAS, Acegi, etc.), data store (LDAP, database, flat-file, etc.), or process (e.g. provisioning/de-provisioning requests, auditing, reporting, etc.).</p>

<p>And while this inconsistency can be beneficial to the extent that it allows each system to implement authorization in the way that is easiest or most effective within that context, across the organization as a whole, managing authorization separately in each system is a serious bane, incurring significant costs in terms of time, resources, and quality. These costs are most evident to the organization in the areas of administration, development, reporting, and auditing.</p>

<h3>Administration</h3>

<p>Any system which manages authorization must provide some mechanism for allowing administrators to change access privileges for users, whether by using a nice GUI, editing a configuration file, or directly manipulating rows/columns in an underlying database. As a user's status changes (e.g. they get promoted, quit, take on new accounts, etc.), these tools must be used to re-provision permissions accordingly. Depending on the number of systems, however, this can be an extremely difficult, time intensive, and error-prone process. A simple resignation of a single employee, for example, could necessitate the re-provisioning of this user's access across dozens of different systems, executed by a handful of different administrators.</p>

<h3>Development</h3>

<p>For systems developed and maintained internally, authorization, like other cross-cutting concerns (e.g. authentication, logging, etc.) should ideally be implemented using a similar set of tools and patterns in order to eliminate duplication of work, maintain quality, and enable developers to translate knowledge or skills from one system to another. Unfortunately, in larger organizations, this is often not the case: authorization is implemented differently for every application, using the approach, patterns, and tools selected by the development team, usually with no concern for commonality or re-use across the organization. Whether a new project uses Spring Security, AzMan, or some other custom solution typically depends on the whims and proclivities of the developers, and the result of reinventing the wheel like this is higher development cost, lower quality, and discrepancies in feature set and usability (e.g. fine-grained authorization may be possible in one system while another has a one-size-fits-all/none model).</p>

<h3>Reporting</h3>

<p>A generally accepted principle of authorization is that of least privilege, giving users as little access as possible to perform their job. In complex enterprise environments, where users are in the thousands, upholding this principle is crucial both from a security perspective as well as a regulatory one. And although this seems simple in theory, in practice, when systems all have their own model for authorization, it's easier said than done. The reason is that before we can even ensure what user X should be able to do, we need to first understand what he can do now. To this end, generating a simple report detailing what permissions a user has is crucial. Unfortunately, this simple view is not trivial to produce, entailing the manual (and collaborative task) of going to each system, discovering what the user can do, and then aggregating the individual sets of permissions into one global report. In other words, there is no one report that can tell "what can Joe Smith do across the organization".</p>

<h3>Auditing</h3>

<p>Finally, auditing is another key component of authorization, both from an administration perspective (e.g. "Joe granted permission X to Sandy on 7/20/10") and an enforcement perspective ("e.g. Joe was authorized to approve order 1234 on 8/1/10"). Unfortunately, auditing of this kind is implemented inconsistently at best or not at all at worst. Piecing together how a user's permissions changed or what a user did on any given day, across the organization, with a model of decentralized authorization, is virtually impossible, necessitating scouring through different log files, database tables, etc.</p>

<h3>Conclusion</h3>

<p>These are just a few problems of implementing authorization independently across different systems in an organization. In later posts I'd like to explain how steps can be taken to centralize some elements of authorization, to the benefit of administration, development, reporting, and auditing. As we all know, there is no silver bullet - every decision comes with a set of trade-offs, however given the status quo of decentralized authorization, it's clear we can do better!</p>				]]>			</description>
			<pubDate>Mon, 26 Jul 2010 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2010/the-problems-of-decentralized-authorization.php</guid>
		</item>
		<item>
			<title>An Architect's Morality</title>
			<link>http://www.bennorthrop.com/Essays/2010/architect-morality.php</link>
			<description>
				<![CDATA[				<p>There was an interesting <a href="http://www.nature.com/nature/journal/v464/n7288/full/464490a.html">article in Nature</a>, arguing that our moral intuitions are formed as much by rational deliberation as by our experiences (despite the latter being more en vogue in academic circles - who knew!). 
</p>
<p>
 It got me thinking about how in any field (whether it be software development or biology, finance, etc.) people have very finely developed intuitions about what is "right" or "wrong" - something that seems akin to moral judgement.  This happens in software development without a doubt - people who have been in the field for a while can have very powerful, immediate, gut reactions to problems - they just know that a certain path is "right" or "wrong".
</p>

<p>The question I'm kicking around is, in software development, <b>how are our "moral" intuitions best formed</b> - by rational deliberation (e.g. reading, observing, studying, listening) or personal experience (playing many roles, living in the trenches)?  In other words, which route would lead to greater "moral wisdom" -  more study or more lived experiences?
</p>  

<p>
(This question is a lot like the kerfuffle about Justice Sotomayor's "wise latina" comments  months back - is she more "wise", coming from a rough neighborhood in the Bronx, than someone who came from the upper-middle class 'burbs?)
</p>

<p>
My sense is that no amount of study or observation can make up for living in the trenches and feeling the pain of bad decisions (your own and others'!).  I can read all day about why unit testing is great, but it doesn't sink in to the level of  "moral intuition" until I live through an experience where there's a million lines of code, no unit tests, and so no clue as to whether your change broke something else or not.  
</p>

<p>
Anyway, just a thought...
</p>				]]>			</description>
			<pubDate>Thu, 20 May 2010 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2010/architect-morality.php</guid>
		</item>
		<item>
			<title>Collective Code Ownership and Craftsmanship</title>
			<link>http://www.bennorthrop.com/Essays/2010/collective_code_ownership.php</link>
			<description>
				<![CDATA[				<p><a href="http://en.wikipedia.org/wiki/Agile_software_development">Agile</a> methodologies hinge on a model of <a href="http://c2.com/cgi/wiki?CollectiveCodeOwnership">collective code ownership</a>  - basically, the idea is:</p>

<p class="indentableSubtle">
I may work on module A this iteration and you on module B, but next iteration I may work on B and you on C.  
</p>

<p>
No developer has sole responsibility for any piece of the system, we all own it together.  If I need to update some piece of the system to implement my assigned <a href="http://en.wikipedia.org/wiki/User_story">user story</a>, I can do it, with the caveat that <a href="http://www.bennorthrop.com/Home/Blog/unit_testing_daos_and_database_code.php">unit tests</a> should pass and probably some quality check should be met (e.g. <a href="http://www.bennorthrop.com/Essays/2008/code_review_potluck.php">peer review</a>, etc.).  
</p>
<p>
In any non-trivially sized team, this is probably a necessity; the alternative model, <a href="http://c2.com/cgi/wiki?CodeOwnership">strict ownership of code</a>, will just yield unnecessary <a href="http://www.amazon.com/Gridlock-Economy-Ownership-Markets-Innovation/dp/0465029167">gridlock</a>, turf-wars, and <a href="http://www.laputan.org/mud/">code ghettos</a> as developers operate unchecked in their own silo, hording knowledge, and protecting the sanctity of their individual assets at the expense of the overall architecture. 
</p>
<p>
And even knowing this, that individual code ownership isn't really feasible in an organization, I still think that <b>when we accept the model of collective ownership, something important is lost: craftsmanship</b>. 
</p>
<p>Sure, Agile advocates <a href="http://www.artima.com/intv/ownership.html 
">would argue</a> that pride of ownership just extends to the work of the team rather than just that of the individual.  To some degree this does exist, but it's not the same.  When we have ownership of something, whether a design document, an API, or a UI screen, it's our reputation on the line, our creativity and execution that make it a success or failure.  We make decisions on our own, quickly, without having to reach team consensus, for good or for ill, accepting the consequences.  And when it does succeed, we derive a strong satisfaction from knowing that someone found value in what we alone designed and created.   We helped make <i>something</i> better, easier, faster.  The freedom of owning our work is what makes programming fun...and meaningful.
</p>
<p>
Without ownership, this satisfaction is muffled.  When people collectively own everything, no one owns anything in particular.  Collective ownership often means collective design, and so there's less investment in the overall success, because, hey, these aren't necessarily my ideas, they're the group's.  And because everyone's a stakeholder in all the code, decisions are often made via sophistry and compromise, producing an end design that often looks more like a piece of legislation and less like a piece of craftsmanship.
</p>
<p>
It reminds me of a favorite quote of mine from Steinbeck in <a href="http://www.amazon.com/East-Eden-John-Steinbeck/dp/0142000655">East of Eden</a>:
</p>

<div class="indentableSubtle">
Our species is the only creative species, and it has only one creative instrument, the individual mind and spirit of man. Nothing was ever created by two men. There are no good collaborations, whether in music, in art, in poetry, in mathematics, in philosophy. Once the miracle of creation has taken place, the group can build and extend it, but the group never invents anything. The preciousness lies in the lonely mind of a man. 
<br/>
<br/>
And now the forces marshaled around the concept of the group have declared a war of extermination on that preciousness, the mind of man. By disparagement, by starvation, by repressions, forced direction, and the stunning hammerblows of conditioning, the free, roving mind is being pursued, roped, blunted, drugged. It is a sad suicidal course our species seems to have taken.
<br/>
<br/>
And this what I believe: that the free, exploring mind of the individual human is the most valuable thing in the world. And this I would fight for: the freedom of the mind to take any direction it wishes, undirected. And this I must fight against: any idea, religion, or government which limits or destroys the individual. This is what I am and what I am about. I can understand why a system built on a pattern must try to destroy the free mind, for that is one thing which can by inspection destroy such a system. Surely I can understand this, and I hate it and I will fight against it to preserve the one thing that separates us from the uncreative beasts. If the glory can be killed, we are lost. 
</div>
<p>
I know, to argue against collective ownership in the era of wikipedia, social media, and open source is probably insane.  Working collaboratively obviously can produce high quality results, and benefit the collaborator as well.
</p>
<p> Even still, talking to colleagues and friends that do software development on teams, I see this unsatisfied need to own.  Just about every programmer has dreams about their own side project, where he makes the decisions, where he is responsible.  It's this freedom which most of us need, and which produces works of craftsmanship.
</p>				]]>			</description>
			<pubDate>Fri, 16 Apr 2010 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2010/collective_code_ownership.php</guid>
		</item>
		<item>
			<title>Keep it Simple!</title>
			<link>http://www.bennorthrop.com/Essays/2010/cognitive_fluency.php</link>
			<description>
				<![CDATA[				Cognitive fluency is the theory that things that are easier to think about seem to be more true, intelligent, and likeable.  What this means for programmers.				]]>			</description>
			<pubDate>Wed, 07 Apr 2010 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2010/cognitive_fluency.php</guid>
		</item>
		<item>
			<title>Usability, RIA, and GWT - 6 Questions to Ask your Users</title>
			<link>http://www.bennorthrop.com/Essays/2010/usability-ria-and-gwt-6-questions-to-ask-your-users.php</link>
			<description>
				<![CDATA[				<p>
It’s very tempting, given the power and ease of <a href="https://web.archive.org/web/20120907201201/http://code.google.com/webtoolkit/">GWT</a>, to jump in head-first and start building flashy new <a href="https://web.archive.org/web/20120907201201/http://en.wikipedia.org/wiki/Rich_Internet_application">RIA</a> applications for your customers right away. Slow down! Although I’m not generally an advocate of big design up front (<a href="http://www.bennorthrop.com/Home/Blog/2008_01_20_decision_tree.php">BDUF</a>), there are a few usability requirements that I think you’ll want to understand before you start coding – requirements that will fundamentally shape how you design your client-side GWT architecture, and therefore minimize re-work later.
</p>

<p>
So, toward the goal of evoking usability requirements, here are 6 important questions to ask your users or business owners:
</p>

<h3>1. Should the back button be supported and in what capacity?</h3>
<p>
By default, to the end user, a GWT application will just be one URL (for example, www.myshoestore.com/index.html), and so clicking “back” will just redirect the browser to the previous site visited (which is extremely frustrating). For most applications, this won’t cut the mustard – users will need to keep their trusty friend the back button in some capacity.
</p>

<p>
The good news is that GWT provides a very simple mechanism, via the <a href="https://web.archive.org/web/20120907201201/http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/History.html">History</a> class, to append tokens to the end of the URL (e.g. “www.myshoestore.com/index.html#FindShoe”), in effect creating virtual “pages” or navigation points within the application. Clicking back, using this solution, will revert the browser to the previous token, not the previous site (although it’s on you, in your code, to refresh the state of the application to correspond with the changed token).
</p>

<p>
The tricky part here, in my experience, is not the implementation, but rather defining with your users where these navigation points are within your application. Remember that this is RIA, so anything’s possible – navigation points can be as fine grain as needed. For example, a user could expand a node in a <a href="https://web.archive.org/web/20120907201201/http://gwt.google.com/samples/Showcase/Showcase.html#!CwTree">tree widget</a>, click back, and the app could “un-expand” that node. This might be unnecessarily fine-grained, but it is possible. Most likely, however, navigation points are more coarse grain, for instance different “views” in your application (like in Gmail with the “Inbox” view, the “Compose” view, etc.).
</p>

<p>
Whatever the decision, it’s critical to define where these points are up front so that they can be built into the application framework.
</p>

<h3> 2. Which screens can be bookmarked?</h3>
<p>
It’s often the case that users will want to share “places” within your application with others, and while coding for back button support (see above) will take you a step in that direction, it won’t get you all the way there. For instance, if a user does a search for “Nike” and the token “#SearchShoe” is added to the url (e.g. http://www.myshoestore.com/index.html#SearchShoe), when the user shares this URL with a friend, there will still not be enough context in the URL itself to let the application know to load not just the “Search” page but also with the “Nike” result set.
</p>

<p>
The solution here is to use tokens in the same way we used the query string in traditional web applications – so what used to be http://www.myshoestore.com/search.jsp?shoe=Nike in GWT could now be http://www.myshoestore.com/index.html#SearchShoe-Nike. Again, using the History class, the token “SearchShoe-Nike” would be read, parsed, and the appropriate search result would be loaded.
Again, like with back button, the difficulty is not necessarily in writing this code, but understanding up-front which views in your application are “bookmarkable”, and ensuring that your framework supports this.
</p>


<h3>3. Which widgets will you support?</h3>
<p>
GWT out of the box comes with a <a href="https://web.archive.org/web/20120907201201/http://gwt.google.com/samples/Showcase/Showcase.html">rich set of widgets</a> (trees, grids, menu bars, etc.) that alone will be a huge improvement over the clunky, static HTML components of the traditional web application (think text boxes, buttons, checkboxes, etc.). Oftentimes these will be all you need, but in some cases users will want more.
</p>

<p>
Fortunately, a number of very utilitarian, high-quality, and flashy open source and commercial widgets are available – things like <a href="https://web.archive.org/web/20120907201201/http://google.latest.gwt-web-calendar.appspot.com/">calendars</a>, <a href="https://web.archive.org/web/20120907201201/http://code.google.com/p/gchart/">charts</a>, or <a href="https://web.archive.org/web/20120907201201/http://www.extjs.com/products/gwt/">drag-and-drop</a>, etc. Beware, however, because this extra UI bling comes at a price. Off-the-shelf widgets can degrade performance, add application complexity, decrease UI consistency, and cause license problems. In my experience, it’s important, up-front, to assess the general UI needs of the users, identify the definitive set of widgets that will be supported within the application, and then stick to it.
</p>

<p>
In many cases, trade-offs will have to be made. For example, in a recent project, despite its power and pizzazz, we decided against leveraging <a href="https://web.archive.org/web/20120907201201/http://code.google.com/p/gwt-ext/">GWT-EXT</a> since we perceived the costs to complexity and performance to be too high for our relatively small application.
Again, designers, users, and even developers will probably want to take an ala carte approach (a widget from here, a widget from there), but it’s important to keep the big picture in mind, and get everyone on the same page as soon as possible with respect to which widgets are in and out of bounds.
</p>

<h3>4. Is Internationalization a requirement?</h3>
<p>
GWT has excellent <a href="https://web.archive.org/web/20120907201201/http://code.google.com/webtoolkit/doc/latest/DevGuideI18n.html">support for internationalization</a>, but as with any other application, this is a non-functional requirement that is absolutely crucial to know up-front. Externalizing presentation text after the application has been built is time-consuming, risky, and generally not good for your constitution.
</p>


<h3>5. How will input validation behave?</h3>
<p>
Most every enterprise application validates user input to some degree, and as any developer knows, this can be done in any number of different ways. For example, in traditional web applications, it was most common that a user would enter all of the data, submit the form, and then the system would check the input and inform the user of any validation errors. Obviously with RIA a richer set of interaction patterns are possible – for instance, data can be validated “just-in-time”, as the user enters it, rather than waiting until the entire form is submitted.
</p>

<p>
Whatever the right interaction pattern is for your application, it’s important to define this up-front as well, and stick to it for all screens. Knowing how validation should behave will help you pick or design the right validation framework (GWT does not come with validation out of the box but there are <a href="https://web.archive.org/web/20120907201201/http://code.google.com/p/gwt-validation/">open source libraries</a>), and will help ensure that input is validated consistently across your entire application. Failing to do so, and therefore letting developers determine how to validate input on their own screens, is a recipe for complexity, redundancy, and inconsistency.
</p>


<h3>6. What happens on asynchronous calls?</h3>
<p>
GWT is obviously based on an <a href="https://web.archive.org/web/20120907201201/http://en.wikipedia.org/wiki/Ajax_(programming)">AJAX</a> model, making many asynchronous calls via Javascript rather than synchronous page loads. It’s important to know, however, the expectations of the user while these asynchronous calls are being made. Is the entire application frozen until the call returns? Or is the converse true, and the user can still some pieces or components? Which pieces? Should the user be able to cancel an asynchronous call (and what would this mean)? Should a “Progress” bar be shown? And so on.
</p>
<p>
Because asynchronous calls are the backbone of a GWT application, it’ll be helpful to understand their usability requirements early. In a previous project, we implemented a custom <a href="https://web.archive.org/web/20120907201201/http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/rpc/AsyncCallback.html">AsyncCallback</a> class that showed an “in progress” <a href="https://web.archive.org/web/20120907201201/http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/user/client/ui/DialogBox.html">modal dialog box</a> whenever an asynchronous call was made to the server. This obviously wouldn’t suit all needs, but it worked for our users.
</p>

<h3>Conclusion</h3>
<p>
In conclusion, while definitely not an exhaustive list, I hope these questions at least sparked some thought as to what types of things you’ll want to ask your users and business owners prior to jumping into your GWT code.
</p>
<p>
And of course I’d love to hear any suggestions or experiences you have. What usability questions would you suggest asking users up front? Please share. Thanks!
</p>				]]>			</description>
			<pubDate>Thu, 25 Mar 2010 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2010/usability-ria-and-gwt-6-questions-to-ask-your-users.php</guid>
		</item>
		<item>
			<title>Using Code Metrics with Purpose</title>
			<link>http://www.bennorthrop.com/Essays/2009/using-code-metrics-with-purpose.php</link>
			<description>
				<![CDATA[				<p>
I know plenty of developers who, at a tactical level, have had success with <a href="https://web.archive.org/web/20120325172737/http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis">static source code analysis tools</a>, using them to help find and root out bad <a href="https://web.archive.org/web/20120325172737/http://martinfowler.com/bliki/CodeSmell.html">code smells</a>. When <a href="https://web.archive.org/web/20120325172737/http://pmd.sourceforge.net/">PMD</a> tells us there's an empty catch block at line 207, for instance, it's pretty straight-forward what to do.
</p>

<p>
At an aggregate level, however, code metrics are seldom so helpful or straight-forward. When seeing that a source tree has 160,000 lines of code or an average <a href="https://web.archive.org/web/20120325172737/http://en.wikipedia.org/wiki/Cyclomatic_complexity">cyclomatic complexity</a> of 4.12, our first thought is usually "interesting!", followed shortly by "well, now what?".
</p>

<p>
The problem is, in my experience, we often look at our code metrics in isolation, without good comparison points, leaving us to wonder whether the numbers we see are big or small, typical or abnormal, good or bad. In the end, it's not clear what to do, if anything.
</p>

<p>
For code metrics to have any real strategic value, whether it's justifying a major refactoring effort to the executive team or just proving that the recent adoption of some new practice (e.g. code reviews, automated testing, etc.) actually had the salubrious effect that you said it would, they must be looked at within some broader context. And there must be a purpose. Otherwise they're just interesting numbers, no more no less.
</p>

<p>
So, to that end, here's a very simple, low-overhead approach I've taken on a few projects, with some success'
</p>

<h3>Define a Purpose</h3>
If code metrics are to actually be <a href="https://web.archive.org/web/20120325172737/http://devver.net/blog/2009/10/improving-code-using-metric-fu/">useful and not just interesting</a>, there must be some clear business-relevant question that you're trying answering. Here are a few examples:
</p>
<ul>
  <li>What is the pace of development? Are we moving slower or faster than before?</li>
  <li>Is the code inherently difficult to maintain? Are there modules that are hopeless?</li>
  <li>Should we expect greater or fewer bugs in this iteration? In general, is quality improving or getting worse?</li>
</ul>
<p>


<h3>Pick which Code Metrics to Use</h3>
<p>
Once it's clear the questions you're trying to answer, the right metrics and tools can then be picked to help build your case. Here are a few metrics and tools (Java-based) to consider, but there are plenty more:
</p>

<ul>
  <li>Lines of code (<a href="https://web.archive.org/web/20150721205912/http://kclee.de/clemens/java/javancss/">JavaNCSS</a>, <a href="https://web.archive.org/web/20150721205912/http://cloc.sourceforge.net/">Cloc</a>)</li>
  <li>Code complexity (JavaNCSS, <a href="https://web.archive.org/web/20150721205912/http://pmd.sourceforge.net/">PMD</a>, <a href="https://web.archive.org/web/20150721205912/http://checkstyle.sourceforge.net/">CheckStyle</a>)</li>
  <li>Unit Test Coverage (<a href="https://web.archive.org/web/20150721205912/http://cobertura.sourceforge.net/">Cobertura</a>)</li>
  <li>Copy-paste instances (PMD)</li>
  <li>Style violations (CheckStyle)</li>
  <li>Design violations (PMD, CheckStyle, <a href="https://web.archive.org/web/20150721205912/http://findbugs.sourceforge.net/">FindBugs</a>)</li>
  <li>Possible bugs (FindBugs)</li>
  <li>Number of check-ins</li>
</ul>

<p>
The important thing, again, is that these metrics map to some business question you're interested in. Less is more, in my experience - it's very easy to get lost in a sea of code statistics, so spend your time only on numbers that could have some practical impact, avoiding those that are inexact, nebulous, inaccurate, or just generally not useful.
</p>


<h3>Track Code Metrics over Time</h3>
<p>
Very often your question is time-oriented - i.e. "are things getting better or worse"? If that's the case, then metrics can be tracked over time, either by iteration, sprint, or release, or by day, week, or month.
</p>

<p>
And although there are a few tools that do this aggregation for you (<a href="https://web.archive.org/web/20150721205912/http://metric-fu.rubyforge.org/">metric_fu</a> for Ruby, <a href="https://web.archive.org/web/20150721205912/http://qalab.sourceforge.net/">QALab</a> or <a href="https://web.archive.org/web/20150721205912/http://www.bennorthrop.com/pmdreports/pmdreports.php">PMDReports</a> for Java, etc.), I've found that few give me exactly what I need with little setup or configuration hassle. In my explorations, I've found it easier to just use the tools I need separately, and aggregate the metrics (dare I say it!) manually in a spreadsheet. For example, two metrics I often keep track of are lines of code and average cyclomatic complexity.
</p>

<p>
For calculating the lines of code I use a nifty tool called <a href="https://web.archive.org/web/20150721205912/http://cloc.sourceforge.net/">Cloc</a> (which take no more than 5 minutes to set up):
</p>

<pre><code>
  C:> cloc codebasemyprojsrc
</code></pre>

<p>
...which gives me something like this:
</p>

<p align="center"><img src="cloc.png"></p>


<p>
For the complexity statistics, I use <a href="https://web.archive.org/web/20150721205912/http://kclee.de/clemens/java/javancss/">JavaNCSS</a> plus a <a href="https://web.archive.org/web/20150721205912/http://www.bennorthrop.com/Misc/javancss_filter_getters_and_setters.php">simple program I wrote</a> to filter out the getters and setters (since these can significantly skew obscure complexity numbers, making your system look a lot simpler than it probably is!):
</p>


<pre><code>
  C: javancss -function -recursive c:codebasemyprojsrc | java FilterGettersAndSetters
</code></pre>

<p>
...which gives me this:
</p>

<p align="center"><img src="javancss.png"></p>


<p>Setting up these tools (downloading, putting things in the path and classpath, etc.) takes maybe a half an hour, and then each time I run them, just seconds. Typically, I'll do this at the end of every sprint, put the metrics in a spread sheet, and then generate a handy graph that I can send to the team or use in a strategy discussion or status report.
</p>

<p align="center"><img src="average-complexity.png"></p>

<p>Note that without the context of time, seeing a complexity score of 3.5 alone doesn't mean much. Knowing, however, that complexity increased from 2.4 in the last sprint to 3.5 in this sprint does - it means something happened, whether too much functionality was fit into the most recent sprint resulting in a slip in quality, or perhaps a new junior developer joined the project, and probably needs to have his code reviewed.
</p>

<h3>Compare Code Metrics across Projects</h3>
<p>
Another way to give your metrics meaning is to compare them against other projects - whether internal to your organization ("look, project A has 12% unit test coverage rate whereas project B has 78%!") or even with other open source projects ("our project has an average cyclomatic complexity of 4.57, but Spring, Hibernate, and Struts all have less than 2.5"). Although your sample size probably won't be statistically significant, it can give a good rough benchmark to help you determine what's acceptable and what merits concern.
</p>

<p align="center"><img src="average-complexity-project.png"></p>

<p>Note: these are just hypothetical numbers to show how metrics could be used!
Again, with little effort, these metrics can be collected manually using simple static code analysis tools, as long as you know what you're looking for.
</p>

<h3>Conclusion</h3>
<p>In the end, code metrics alone won't tell the whole story, but used thoughtfully and purposefully, they can be invaluable when making strategic product or project decisions - for example, helping to illuminate maintainability problem areas in your architecture, predict where and when quality slippages would be expected, and, in general, determine whether the ship is going in the right direction or not.</p>

<p>Anyway, I'd like to hear about your experiences with using code metrics. Have aggregate statistics helped in any way? Which ones? How have you used them? And which tools have been useful?</p>				]]>			</description>
			<pubDate>Mon, 30 Nov 2009 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2009/using-code-metrics-with-purpose.php</guid>
		</item>
		<item>
			<title>SOA and Authorization: What's so hard about it anyway?</title>
			<link>http://www.bennorthrop.com/Essays/2009/soa-and-authorization-part-1-whats-so-hard-about-it-anyway.php</link>
			<description>
				<![CDATA[				<p>Thereâ€™s plenty of talk about security and SOA (or should I <a href="http://apsblog.burtongroup.com/2009/01/soa-is-dead-long-live-services.html">just say services</a> now?), but the vast majority seems to cover only the issues of <a href="http://it.toolbox.com/blogs/the-soa-blog/soa-security-architecture-11431">authentication</a> and <a href="http://www.mainframe-exec.com/articles/?p=53">identity management</a>, and neglects the equally important problem of authorization (<a href="#footnote1">*1</a>). Although I can't claim to be a security expert, in a series of posts, Iâ€™d like to share some of my thoughts and experiences on implementing authorization in the world of service-oriented architectures.</p>
<!--more-->
<p>In this first post, Iâ€™d like to take a quick trip through some of the basic terms and definitions of authorization, laying the conceptual groundwork for the later posts. Ok, letâ€™s get started!</p>
<h3>Access Control Policies</h3>
<p>In general terms, an authorization or access control policy defines whether a given <strong><em>subject</em></strong> can perform an <strong><em>action</em></strong> on a particular <strong><em>object</em></strong>. For example, a policy could determine whether "Hines Ward" (subject) can delete a charge (action) from "Mike Tomlin's" account (object). (<a href="#footnote2">*2</a>) This decision, to grant or deny access to a specific object or resource, is commonly based on one or more the following four factors:</p>
<ol>
<li><strong>Role-based (<a href="http://en.wikipedia.org/wiki/Role-based_access_control">RBAC</a>):</strong> Most often, access to a particular operation is granted by virtue of a specific role that a subject is affiliated with. For example, the ability to remove a charge could be granted to any user with an "Account Admin" role.</li>
<li><strong>Attribute-based (<a href="http://www.isso.sparta.com/documents/abac.pdf">ABAC</a>):</strong> Access control may also be based on some inherent attribute of the user or object. For example, Account Admins from the Northeast region (user attribute) may remove charges from customers from the Pittsburgh district (object attribute). In this way, access control policies define a relationship from subject to object that must exist in order to perform the action.</li>
<li><strong>Consumer-based: </strong> In an SOA world, service endpoints may be open to the network, and so it may be necessary to manage access to an operation based on the consumer of that service. For example, ensure that only the Customer Service may invoke operation "getAccountInfo(customerId)" on the Accounting Service.</li>
<li><strong>Time-based:</strong> It is sometimes necessary to restrict access to a particular resource based on the time of day or calendar date - for instance, "only allow changes to accounts during normal business hours, 8am - 5pm".</li>
</ol>
<h3>Access vs. Filtering</h3>
<p>Beyond the subject-action-object form of access policy defined above, there's another type of authorization that's just as crucial in enterprise applications: <a href="http://books.google.com/books?id=SQpsrqT5cm4C&pg=PA427&lpg=PA427&dq=">response filtering</a>. Although both types are based on the authorization factors defined above (role, attribute, consumer, time), <strong><em>filtering</em></strong> policies determine not whether a user be restricted to a specific operation on an object, but rather that the data that is retrieved from an operation be narrowed to only those records or fields that the subject is authorized to view . For example, when user "Hines Ward" of the "Pittsburgh" region calls operation "fetchAccounts()", the system can allow access, but return only those account records for customers in the "Pittsburgh" region, and not account records for customers in other regions.</p>
<p>In my experience, these two types of authorization ("access" and "filtering") are often mistakenly conflated, and so are assumed to be satisfied by the same authorization framework. Unfortunately, this isn't usually possible - a framework or solution that protects access to a resource (e.g. URL, endpoint, etc.) is fundamentally different than one that filters result sets or message bodies. It's important, therefore, to identify the type of authorization requirements that exist to guide downstream design.</p>
<h3>Architectural Components of Authorization</h3>
<p>Having trudged through some of the conceptual territory of authorization, we can now dig into some of the tangible, implementation details. In any authorization solution, most of the following architectural entities exists in some form or another, though they may not be clearly abstracted:</p>
<ul>
<li><strong>Policy Definitions:</strong> Where policies are actually defined and stored. In the case of simple RBAC models, this may just be a database managing relations between users, roles, and entitlements, but in more complex ABAC models, these could be separately defined policy files (e.g. <a href="http://www.oasis-open.org/committees/xacml/">XACML</a>). Note that policies are also quite often found "hard-coded" in business logic or UI code (e.g. "if(user.group == 'admin') showButton()"). (<a href="#footnote3">*3</a>)</li>
<li><strong>User Store:</strong> The central repository for core user information (e.g. name, id, etc.) - think LDAP for enterprise apps, or perhaps just a "user" table in a RDBMS for smaller apps.</li>
<li><strong>Attribute Store (i.e. Data):</strong> As I defined it in the section above, authorization attributes (whether subject or object) are just plain old business data that happens to be relevant to determining access for a user. For instance, in the example above, the customer's region is a relevant authorization attribute, and would likely just be stored as a "region_id" column on the "customer" table.</li>
<li><strong>Policy Enforcement Point (<a href="http://www.birds-eye.net/definition/p/pep-policy_enforcement_point.shtml">PEP</a>):</strong> The place in the architecture that enforces access control. For example, in a simple web-application, this could be a servlet filter that protects the resource.</li>
<li><strong>Policy Decision Point (<a href="http://www.birds-eye.net/definition/p/pdp-policy_decision_point.shtml">PDP</a>):</strong> The place in the architecture that makes access control decisions. Note, in smaller applications, this likely is the same as the PEP, but in larger, distributed applications, it could be different. Also, note that in some cases Policy Definitions are embedded within the Policy Decision point, but may be externalized (e.g. XACML).</li>
<li><strong>Response Filter:</strong> The entity responsible for winnowing a data set down to only those records a user is authorized to view.</li>
</ul>
<h3>A "Simple", non-SOA Example</h3>
<p>Already, authorization seems a little harrowing - and we haven't even gotten to SOA yet! Before we do, as a final step toward laying the authorization groundwork, let's map some of the concepts and architectural elements defined above to territory that's most likely familiar - a simple, stand-alone web application.</p>
<p><img class="size-full wp-image-1079" style="width: 540px; height: 503px; display: block; margin-left: auto; margin-right: auto;" title="simple_authorization3" src="simple_authorization3.gif" alt="simple_authorization3" width="540" height="503"/></p>
<p>As the diagram above illustrates, authorization in this "simplest" case can still be rather complex. Policy definitions and decision points are scattered throughout the different layers of the architecture - an interceptor responsible for protecting resources (i.e. URLs) based on roles, the UI for showing/hiding information based on permissions, the business logic for executing complex, attribute-based authorization decisions (e.g. customer can only view their own account), and the data access layer (or database) for filtering data sets to only those records the user is authorized to view. The database stores user, role, permission, and attribute data, queried by the different PDPs.</p>
<h3>What's Different in SOA?</h3>
<p>As I've written about <a href="http://www.bennorthrop.com/Essays/2009/soa-and-the-n-1-selects-problem.php">before</a>, SOA puts a new twist on old problems, and it's the same for authorization. What was a delicate but well-traversed and tractable issue before, is an <em>extremely</em> complex and risk-ridden problem when you stir in the ingredients of a SOA-based enterprise architecture - loosely-coupled services, registries, process engines, stand-alone user interfaces, ldap directories, etc. Although I'll cover these pitfalls in future posts, here are a few monkey-wrenches SOA throws into the authorization machine:</p>
<ul>
<li>Is there a central repository for all users of an enterprise?</li>
<li>Is there a central repository for roles and permissions for all services in the enterprise? If not, does each service maintain its own unique set of roles and permissions for users?</li>
<li>How are authorization attributes propagated between services?</li>
<li>Can policies be managed centrally, such that changes to access control necessitates only going to one place, and not to every individual service?</li>
<li>What happens when a policy depends on retrieving data that is not local to the service it resides in? In other words, can policies call other services to retrieve authorization attributes they need to make allow/deny decisions?</li>
<li>How can a service ensure that only other services call it?</li>
<li>To what extent can policies be modified at run-time? How can they be managed?</li>
</ul>
<p>And this is just the tip of the iceberg! In my humble opinion, most of these issues boil down to the same central vs. local diametric decision - i.e. what authorization components should be centrally shared by all services (e.g. User store/service, etc.) and which should be locally (read: redundantly) defined, within each service. Obviously, there are major trade-offs on both sides - performance, maintainability, scalability, and reliability to name just a few.</p>
<p>To sum up, I hope I was able to lay some of the building blocks of authorization. In later posts, I'd like to touch on different approaches, patterns, products, and standards for authorization in SOA. I'd love to hear what you think so far, so please feel free to drop me a comment!</p>
<h3>Endnotes</h3>
<p><a name="footnote1"></a>1. For those people who get these mixed up (I used to be one!), authentication tackles the problem of verifying that the user is who he says he is, and identity management with the multi-faceted problem of how users are given identities and how these identities are propagated. Authorization, on the other hand, assumes these first two issues are solved, and deals with ensuring that a user may do only what he has permission to do.</p>
<p><a name="footnote2"></a>2. Yup, I'm a <a href="http://www.pittsburghsteelers.com">Steeler</a> fan:)</p>
<p><a name="footnote3"></a>3. The dividing line between "business logic" and "authorization policy" is often fuzzy - and it's not always clear whether a requirement should be implemented within the confines of the authorization framework, or whether it can be happily embedded within normal business logic code. In an email comment from <a href="http://www.summa-tech.com/blog/2009/05/06/is-all-open-source-software-really-free/">Rick</a>, he suggested that a good litmus test is the requirements around manageability - e.g. who is responsible for managing access rights, does the logic need to be configurable at run time, etc. I think this is a great point.</p>				]]>			</description>
			<pubDate>Thu, 30 Jul 2009 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2009/soa-and-authorization-part-1-whats-so-hard-about-it-anyway.php</guid>
		</item>
		<item>
			<title>Anchors Away!</title>
			<link>http://www.bennorthrop.com/Essays/2009/anchoring_estimates.php</link>
			<description>
				<![CDATA[				How can a developer communicate an honest, but high, estimate to management?  Try the concept of an anchor, from behavioral economics.				]]>			</description>
			<pubDate>Tue, 21 Jul 2009 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2009/anchoring_estimates.php</guid>
		</item>
		<item>
			<title>What is 'Good' Software Architecture?</title>
			<link>http://www.bennorthrop.com/Essays/2009/what_is_good_architecture.php</link>
			<description>
				<![CDATA[				Can "good" architecture be defined in purely pragmatic terms? If the system fulfills the needs of the person or organization who funds its existence, it's successful ipso facto!				]]>			</description>
			<pubDate>Thu, 30 Apr 2009 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2009/what_is_good_architecture.php</guid>
		</item>
		<item>
			<title>6 Tips for Managing Property Files with Spring</title>
			<link>http://www.bennorthrop.com/Essays/2009/6-tips-for-managing-property-files-with-spring.php</link>
			<description>
				<![CDATA[				<p>What could be simpler than property files? In an enterprise application, it turns out, many things! In this post Iâ€™ll take a look at a few subtle complexities to managing properties in an enterprise Java Spring application, and hopefully demonstrate how a little fore-thought in design can yield big savings in terms of time, confusion, bugs, and gray hair down the road.</p>
<!--more-->
<h3>Types of Properties</h3>
<p>Before designing an approach to managing property files, it's critical first to understand the <em>types</em> of properties are to be managed. Here are four characteristics to consider:</p>
<ul>
<ul>
<li>Are some properties <strong>environment specific</strong> â€“ in other words, do they have a different value in one environment than another? For example, a database connection string would differ in the TEST environment than it would the PROD environment.</li>
<li>Do any properties contain <strong>sensitive information</strong>, like passwords or credentials, that canâ€™t sit in plain text in the deployment unit (e.g. WAR, EAR)?</li>
<li>Do any properties need to be located <strong>external</strong> from the deployment unit (e.g. on the file system rather than in the WAR, perhaps to be managed by a systems administrator)?</li>
<li>Should properties be <strong>dynamic</strong>, in the sense that they can be updated at runtime (i.e. without requiring a restart of the application)?</li>
</ul>
</ul>
<p>Each of these special characteristics adds a degree of complexity to applications - necessitating additional infrastructure beyond the simple Java <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/Properties.html">Properties</a> class.</p>
<h3>Springâ€™s PropertyPlaceholderConfigurer</h3>
<p>Fortunately for us, the Spring framework, with the <a href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.html">PropertyPlaceholderConfigurer</a> and <a href="http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/beans/factory/config/PropertyOverrideConfigurer.html">PropertyOverrideConfigurer</a>, provides the features and hooks we need to manage these cases (with the exception â€œdynamicâ€ properties). And true to its philosophy, Spring makes simple things <em>simple</em>, and complicated things <em>possible</em>.</p>
<p>The PropertyPlaceholderConfigurer allows properties to be pulled in to the application context file. For example, in the simplest case, a property â€œdb.userâ€ defined in database.properties could be pulled into the ${db.user} placeholder:</p>
<pre class="xml:nocontrols">&lt;bean id="propertyPlaceholderConfigurer"<br>class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;<br> &lt;property name="locations"&gt;<br> &lt;list&gt;<br> &lt;value&gt;classpath:database.properties&lt;/value&gt;<br> &lt;/list&gt;<br> &lt;/property&gt;<br>&lt;/bean&gt;<br><br>&lt;bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"&gt;<br> &lt;property name="user" value="${db.user}"/&gt;<br> &lt;property name="password" value="${db.password}"/&gt;<br> ...<br>&lt;/bean&gt;
</pre>
<p>The PropertyOverrideConfigurer works in the opposite way, pushing properties from property files into properties in the context file (without having to specifically define a place holder â€“ e.g. ${db.user}). These are both well documented in the Spring API and <a href="http://static.springframework.org/spring/docs/2.5.x/reference/index.html">documentation</a>.</p>
<h3>Tips</h3>
<p>Given the different possible types of properties, and Spring's property framework, here are a few tips for managing them:</p>
<p>1) Consider using a <strong>JVM System property</strong> that sets the environment of the machine (e.g. "my.env=TEST"), telling the configurer which property file to use. For example:</p>
<pre class="xml:nocontrols">  &lt;context:property-placeholder
      location="classpath:db-${my.env}.properties"/&gt;
</pre>
<p>If the "my.env" property was set to "TEST", then obviously the PropertyPlacementConfigurer would look for a file called "db-TEST.properties". For Tomcat, this property can be set in the admin console or defined in a startup script (e.g. "-Dmy.env=TEST") - neither of which is <a href="http://stackoverflow.com/questions/372686/how-can-i-specify-system-properties-in-tomcat-configuration-on-startup">very elegant</a>. Alternatively, it is possible to use JNDI with Tomcat, defining "my.env" in the <a href="http://www.nabble.com/Global-JNDI-and-Tomcat-td17329386.html">server.xml and the context.xml of the web app</a>. (Note, there are of course many other ways to solve this environment-specific problem, but this is an easy and relatively straight-forward one.)</p>
<p>&nbsp;</p>
<p>2) It may be necessary to set the <strong>ignoreUnresolvablePlaceholders</strong> to true for any PropertyPlaceholderConfigurer, which will ensure that a configurer wonâ€™t fail if it canâ€™t find a property. Why would this be a good thing? Oftentimes, one context file will import other context files, and each may have their own configurer. If ignoreUnresolvablePlaceholders is set to false (the default), then one configure would fail if it couldnâ€™t find the property, even if another configurer down-stream could find it (see good explanation <a href="http://tarlogonjava.blogspot.com/2009/02/tips-regarding-springs.html">here</a>). Beware, however, since this will suppress warnings for legitimate missing properties, making for some tough-to-debug configuration problems.</p>
<p>&nbsp;</p>
<p>3) To encrypt properties, subclass the PropertyPlacementConfigurer and override the <strong>convertPropertyValue()</strong> method. For example:</p>
<pre class="java:nocontrols">
<code data-language="java">protected String convertPropertyValue(String strVal) {
  //if strVal starts with â€œ!!â€ then return EncryptUtil.decrypt(strVal)
  // else return strVal
}
</code></pre>
<p>4) Consider using the <strong>systemPropertiesMode</strong> property of the configurer to override properties defined in property files with System properties. For one-off environment specific properties this can be a helpful solution, however, for defining many properties, this configuration can be cumbersone.</p>
<p>&nbsp;</p>
<p>5) For properties that need to be managed <strong>outside of the WAR</strong>, consider using a <strong>System property</strong> to define where the file is located. For example, the property ${ext.prop.dir} could define some default directory on the file system where external property files are kept:</p>
<pre class="xml:nocontrols">&lt;context:property-placeholder
     location="file:///${ext.prop.dir}db.properties"/&gt;
</pre>
<p>This entails, however, that this property is set for any process that leverages the Spring container (e.g. add the param to the <a href="http://agile.csc.ncsu.edu/SEMaterials/tutorials/eclipse/eclipse_tutorial_3.3.html">Run Configuration</a> for integration/unit tests, etc.), otherwise the file would not be found. This can be a pain. To circumvent, the configurer can be overridden â€“ changing the behavior such that it looks to the external directory only if the System property is set, otherwise it pulls from the classpath.</p>
<p>&nbsp;</p>
<p>6) Beware of <strong>redundancy</strong> of environment-specific properties. For example, if the solution is to have one property file for each environment (e.g. â€œdb-test.propertiesâ€, â€œdb-dev.propertiesâ€, etc.), then maintaining these properties can be a bit of a nightmare - if a property "foo" is added, then it would have to be added to the property file for each environment (e.g. DEV, TEST, PROD, etc.). The PropertyOverrideConfigurer is appropriate to eliminate this redundancy, setting the default value in the application context itself, but then the overriding value in a separate file. It's important, however, to document this well, since it can look a bit "magical" to an unsuspecting maintenance developer who sees one value specified in the context file, but another used at runtime.</p>
<h3>Conclusion</h3>
<p>Managing properties for an enterprise application is a little trickier than one might expect. With Spring's property configurers, however, the toughest part is just knowing what you need - the rest comes out of the box, or with some minor extensions.</p>
<p>Hopefully a few of these tips will be useful for you. Please let me know some of your own!</p>				]]>			</description>
			<pubDate>Mon, 20 Apr 2009 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2009/6-tips-for-managing-property-files-with-spring.php</guid>
		</item>
		<item>
			<title>SOA and the N + 1 Selects Problem</title>
			<link>http://www.bennorthrop.com/Essays/2009/soa-and-the-n-plus-one-selects-problem.php</link>
			<description>
				<![CDATA[				<p>
Service Oriented Architectures (or, <a href="http://www.martinfowler.com/articles/microservices.html">microservices</a>, as they're called now) add a new twist to an old problem. Imagine this simple scenario:
</p>

<p class="indentableSubtle">
You are an architect of an online retailer. Your business owners have laid down the gauntlet. Well, not really they've just added a new requirement: they'd like to see a list of all orders for customers matching some specific criteria (e.g. city, name, registration date, etc.). For example, show me all orders for customers named "Holmes" from "Pittsburgh, PA". Further, this isn't for a static report, but rather a dynamic screen in their admin UI.
</p>

<p>
Sounds simple, right? In the old days of integrated applications, it would be - just join the customer and order tables and apply said criteria. Voila!
</p>

<p>
Ahh...but it's a brave new world of SOA, and some old tricks no longer apply. In your architecture, instead of one integrated application, you have two loosely coupled services, Customer and Order. Both services are deployed independently and have their own data - i.e. the Customer service has a Customer data store and the Order service an Order store.
</p>

<p>
The question stands then how can you answer a business question about customers and orders, given that this data spans across multiple services?
</p>

<p align="center"><img src="microservices_n_plus_one.png" align="center"/></p>

<p>Here are four solutions I've come across:</p>

<p>
<b>1. Retrieve from Service:</b> A pure SOA architecture may dictate that access to another service's data necessitates a call through that service's exposed interface - and this is where you come face-to-face with the n + 1 selects problem. In this architecture, your Customer Service would first have to query the customer data store for the list of customers matching the criteria. It would then, for each customer, call the Order service to return all orders associated with that customer. Therefore, for n customers matching the criteria, n + 1 queries would need to be executed (on top of n remote calls to the Order service!). The performance costs here are significant, and I imagine unsatisfactory in most cases.
</p>

<p>
<b>2. Retrieve Directly: </b>Another option would be to open read-only access to the Orders data store from the Customer service. This would improve performance, by saving the remote calls to the Orders service (and perhaps the associated data binding), but still wouldn't circumnavigate the "n + 1 selects" problem, since without a database join from customers to orders, a query of orders for each customer is still necessary.
</p>

<p>
<b>3. Cache Locally: </b>A third route would be to cache another service's data locally (perhaps through some <a href="https://web.archive.org/web/20120325151046/http://blogs.msdn.com/nickmalik/archive/2006/10/25/soa-and-database-coupling.aspx">pub-sub, Master Data Management solution</a>). In the scenario above, some customer specific data could be cached in the Order store, such that finding all orders for customers living in "Pittsburgh" could be handled by the Orders service alone. Alternatively, there could be a special <a href="https://web.archive.org/web/20120325151046/http://www.compositesw.com/solutions/soa.shtml">search service</a> which caches both customer and order data locally, and would be used exclusively to handle queries across data stores.
</p>

<p>
<b>4. Retrieve from Central Database: </b>A fourth solution, not depicted on the diagram, would be to have only one master database from which both services may read and write. Doing so would improve performance and perhaps reduce complexity, but much of the loose-coupling, separation of concerns benefits of your SOA would not be realized - for example, a change to the orders table could have the effect of breaking the Customer service.
</p>

<p>You may argue that this is a straw-man example - in the real world, these services wouldn't exist (e.g. wrong <a href="https://web.archive.org/web/20120325151046/http://blogs.sun.com/crupi/entry/soa_service_granularity">service granularity</a>, etc.). Possibly true. However, any SOA will have multiple services, and some of these services will need access to data that spans other services, so in some form, the problem will still remain.
</p>

<p>Anyway, thanks for reading, and I'd be very interested to hear your thoughts or solutions!</p>				]]>			</description>
			<pubDate>Tue, 17 Feb 2009 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2009/soa-and-the-n-plus-one-selects-problem.php</guid>
		</item>
		<item>
			<title>Building a Better Resume for Developers</title>
			<link>http://www.bennorthrop.com/Essays/2008/a-better-developer-resume.php</link>
			<description>
				<![CDATA[								]]>			</description>
			<pubDate>Fri, 12 Dec 2008 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2008/a-better-developer-resume.php</guid>
		</item>
		<item>
			<title>The Code Review Potluck</title>
			<link>http://www.bennorthrop.com/Essays/2008/code_review_potluck.php</link>
			<description>
				<![CDATA[				Fagan-style code reviews do work, but seldom do we have the time or discipline to actually do them regularly. There is another way. 				]]>			</description>
			<pubDate>Fri, 17 Oct 2008 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2008/code_review_potluck.php</guid>
		</item>
		<item>
			<title>Does Programming to Interfaces Buy Us Anything?</title>
			<link>http://www.bennorthrop.com/Essays/2008/program-to-interface-not-implementation.php</link>
			<description>
				<![CDATA[								]]>			</description>
			<pubDate>Wed, 28 May 2008 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Essays/2008/program-to-interface-not-implementation.php</guid>
		</item>
		<item>
			<title>Deliberative Development</title>
			<link>http://www.bennorthrop.com/Home/Blog/deliberative_development.php</link>
			<description>
				<![CDATA[				Silo development has it's advantages, namely speed. But political philosophy's Deliberative Democracy has something to say about the negative consequences. 				]]>			</description>
			<pubDate>Tue, 22 Apr 2008 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Home/Blog/deliberative_development.php</guid>
		</item>
		<item>
			<title>7 Strategies for Unit Testing DAOs and other Database Code</title>
			<link>http://www.bennorthrop.com/Home/Blog/unit_testing_daos_and_database_code.php</link>
			<description>
				<![CDATA[				Creating repeatably passing unit tests for an enterprise application is hard work, mostly because of the reliance on volatile data. Here are 7 common approaches for testing database code.				]]>			</description>
			<pubDate>Fri, 21 Mar 2008 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Home/Blog/unit_testing_daos_and_database_code.php</guid>
		</item>
		<item>
			<title>Politics and Programming</title>
			<link>http://www.bennorthrop.com/Home/Blog/2008_02_08_politics_and_programming.php</link>
			<description>
				<![CDATA[				We as programmers have beliefs about software development. We as citizens have beliefs about government. Is there any connection or correspondance between the two? 
				]]>			</description>
			<pubDate>Tue, 12 Feb 2008 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Home/Blog/2008_02_08_politics_and_programming.php</guid>
		</item>
		<item>
			<title>The Architect's Dilemma</title>
			<link>http://www.bennorthrop.com/Home/Blog/2008_01_20_decision_tree.php</link>
			<description>
				<![CDATA[				There's a natural tension between the philosophies of up-front design (BDUF) and in-time design (YAGNI). Can decision trees help?				]]>			</description>
			<pubDate>Sun, 20 Jan 2008 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Home/Blog/2008_01_20_decision_tree.php</guid>
		</item>
		<item>
			<title>Managing Code Quality with PMDReports</title>
			<link>http://www.bennorthrop.com/Home/Blog/2008_01_04_pmdreports.php</link>
			<description>
				<![CDATA[				Introducing my pet project, PMDReports, for managing code quality.				]]>			</description>
			<pubDate>Fri, 04 Jan 2008 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Home/Blog/2008_01_04_pmdreports.php</guid>
		</item>
		<item>
			<title>Why are our Programming Gods so Unkempt?</title>
			<link>http://www.bennorthrop.com/Home/Blog/2007_12_17_unkempt.php</link>
			<description>
				<![CDATA[				Does a theory of finite will-power say anything about our software Gods, or the environment we work within?				]]>			</description>
			<pubDate>Mon, 17 Dec 2007 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Home/Blog/2007_12_17_unkempt.php</guid>
		</item>
		<item>
			<title>Is it Irrational to Comment your Code?</title>
			<link>http://www.bennorthrop.com/Home/Blog/2007_11_17_prisoners_dilemma.php</link>
			<description>
				<![CDATA[				We know we should comment code, but will we? Game Theory's Prisoner's Dilemma says, "probably not". 				]]>			</description>
			<pubDate>Sun, 11 Nov 2007 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Home/Blog/2007_11_17_prisoners_dilemma.php</guid>
		</item>
		<item>
			<title>Why Code Quality Tools Work</title>
			<link>http://www.bennorthrop.com/Home/Blog/2007_01_17_code_quality.php</link>
			<description>
				<![CDATA[				Using rational choice theory to explain why PMD, CheckStyle, and other code quality tools work in the real world.				]]>			</description>
			<pubDate>Wed, 17 Jan 2007 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Home/Blog/2007_01_17_code_quality.php</guid>
		</item>
		<item>
			<title>Starting a Design Patterns Discussion Group</title>
			<link>http://www.bennorthrop.com/Home/Blog/2006_11_01_design_patterns.php</link>
			<description>
				<![CDATA[				Once upon a time, I started a design patterns discussion group to slog through that distinguished blue and white book that decorated my bookshelf. Here are my lessons learned. 				]]>			</description>
			<pubDate>Wed, 01 Nov 2006 00:00:00 -0500</pubDate>
			<guid>http://www.bennorthrop.com/Home/Blog/2006_11_01_design_patterns.php</guid>
		</item>
		<item>
			<title>The Search for a Good UML Tool</title>
			<link>http://www.bennorthrop.com/Home/Blog/2006_10_26_uml.php</link>
			<description>
				<![CDATA[				When we want a UML tool, it's most often to help us either design, understand, or maintain. There are a lot of tools out there, and all are not created equal.				]]>			</description>
			<pubDate>Thu, 26 Oct 2006 00:00:00 -0400</pubDate>
			<guid>http://www.bennorthrop.com/Home/Blog/2006_10_26_uml.php</guid>
		</item>
	</channel>
</rss>