Scrum, XP, Management and the Ethics of Agile Software Development

Apple iBooks announcement on the iPad

Apple ibooks announcement on the ipad via ZDNet

At an Apple press event, CEO Steve Jobs shows off the company’s new iBooks app. Users can now browse, read reviews, read a sample excerpt, or just buy books–and the book downloads to a virtual “book shelf.” The software has the support of five of the largest publishers, including Simon & Schuster. (from ZDNet…)

This could be a lot of fun…

  • email
  • Print
  • Digg
  • Reddit
  • StumbleUpon
  • Google Bookmarks
  • del.icio.us
  • LinkedIn
  • Facebook
  • Twitter

When the customer is not the end user

Sorry, we’re unable to load a message from our sponsors. Hulu’s advertising partners allow us to provide a free viewing experience. To ensure advertisements play properly please: Ensure minimum software and bandwidth requirements are met. Confirm all ad-blocking software has been fully disabled. If you continue to experience issues, please email us at support@hulu.com so we can help diagnose the problem.
  • email
  • Print
  • Digg
  • Reddit
  • StumbleUpon
  • Google Bookmarks
  • del.icio.us
  • LinkedIn
  • Facebook
  • Twitter

Consume a feed from a site that doesn’t syndicate using Yahoo Pipes

clownmommy screenshotIt’s surprising how hard it is to subscribe to sites intent on driving traffic to their main page, particularly if you want a subset of content by author or topic.

My wife writes for the nycmoms blog. She wanted to show a list of her recent blogs on her personal blog.

Nycmoms exposes a single feed aggregating recent posts across all authors.

Create a feed

My first iteration was to filter this feed through Yahoo Pipes. Pipes provides a graphical interface for chaining rules for manipulating web content and exposing it in a feed.

I used the “fetch feed” module pointed to the recent posts feed, connected it to the filter module set to only permit items where the author.name contained my wife’s handle.

This produced a correct result. However, only one or two of my wife’s posts are in the “recent posts” feed at any given time.

For the next iteration I found an alternative source outside the blog itself. Being a Yahoo tool, pipes provides a Yahoo search module. So, I searched for the phrase “Posted by KathieH” restricted to the site, nycmomsblog.com.

This produced more but less precise results. It includes additional pages such as my wife’s bio and sorted by relevance not post date.

I used the sort module on the item.updatedon field in the rss feed.

Next I used the filter module to exclude anything that was not an actual post identified by the term: “NYC Moms: KathieH” and piped out to rss.

Then I used the RSS widget in wordpress to expose this feed on my wife’s blog. Done!

Yahoo Pipes Screen Shot

Consume the feed

Except, my wife’s blog began suffering from the dreaded “Fatal Error: Allowed Memory Size” error in the simplepie library used by the RSS widget.

Well documented on the web, this is caused by my service provider’s decision to restrict accounts to 32MB of memory for PHP script execution. This and the 50MB-200MB storage limits were reasonable when I first signed up with my ISP ten years ago but is about as appropriate as using a 80286 processor now.

I decided to switch from server side processing to client side.

Luckily, Yahoo Pipes exposes feeds in the JSONP format. JSON is easily parsed by Javascript in the browser. JSONP is an established workaround (i.e. hack) that allows the client to make requests to third party URL’s without triggering the cross site security restrictions built into current browsers. It simply wraps the data response in a prefix that the browser parses as a function (allowed) as opposed to pure data (not allowed).

Wordpress already uses the jQuery library which is well documented by examples on how to request, parse and render a feed.

I used the getJSON function to retrieve and parse the feed. It is exposed as a nested array containing at the top level, key/value pairs associated with the entire feed and an array of items containing the actual posts.

I loop through the value.items format them into HTML and append them into a div with the id nycmoms_posts. Probably overkill given how fast this all works but I display a loading indicator which I fade out when the loop is complete (from Kyle Meyer).

<div id=”nycmoms”>
<h2>Kathie on <a href=”http://www.nycmomsblog.com/kathieh/”>nycmomsblog.com</a></h2>
<div id=”nycmoms_loading” >…</div>
<ul id=”nycmoms_posts” />
</div>

<style>
#nycmoms { width:250px;min-height:125px;}
#nycmoms_loading { position:absolute;top:0;left:0;width:100%;height:100px;padding:100px 0 0 125px;}
#nycmoms .description, #nycmoms .postdate { font-size:small;}
</style>
<script src=”wp-includes/js/jquery/jquery.js?ver=1.3.2″></script>
<script>

var descriptionPattern = /^(.*) … Posted by Kathie H. on (\w+) (\d+), (\d+) .*$/g

window.onload = function() {

jQuery.getJSON(“http://pipes.yahoo.com/pipes/pipe.run?_id=8a8edd5b1e5181a001892cee910c11fc&_render=json&_callback=?”,
function(data) {
jQuery.each(data.value.items, function(i, post) {
jQuery(“#nycmoms_posts”).append(
‘<li><a href=”‘ + post.link +’”>’ + formatTitle(post.title) + “</a>”
+ “<!– “+formatDescription(post.description)+”–>”
+ “</li>”
) , jQuery(‘#nycmoms_loading’).fadeOut(500);
});
});

}

function formatDescription(description)
{
return description.replace(descriptionPattern, ‘<span=”description>”$1 … </span><span id=”postdate”>posted $2 $3, $4</span>’);
}
function formatTitle(title)
{
return title.replace(/^NYC Moms: /, ”);
}

</script>

  • email
  • Print
  • Digg
  • Reddit
  • StumbleUpon
  • Google Bookmarks
  • del.icio.us
  • LinkedIn
  • Facebook
  • Twitter

FIRST LEGO League Robotics in Brooklyn

2010 FIRST LEGO League Qualifier Brooklyn
FIRST LEGO League (FLL) Robotics Tournament, Brooklyn Borough Qualifier.

FLL is a global program created to get children excited about science and technology. A hands-on program for ages 9 to 16 (9 to 14 in the U.S. and Canada), FLL uses Challenges based on real world scientific problems to engage children in research, problem solving, and engineering. The cornerstone of the program is its Core Values, which emphasize friendly sportsmanship, learning, and community involvement. (more…)

  • email
  • Print
  • Digg
  • Reddit
  • StumbleUpon
  • Google Bookmarks
  • del.icio.us
  • LinkedIn
  • Facebook
  • Twitter

Nine software development aphorisms (that are sometimes true)

  • Beneficial change results from cycles of learning, doing and self-reflection.
  • Success derives from delivering small things of value regularly and often.
  • A discreet piece of work is either done or it is not done.
  • Better to risk a bad decision than make no decision at all.
  • The wisest decision is made just before it can be most efficiently acted upon and no earlier.
  • Most features will receive little or no use. 60% of what you want is better than 100%.
  • Plans document one scenario that will not happen and describe some other application than the one that was built.
  • On time and on budget are not synonyms for success.
  • In human endeavor, every enlightening truth contains a lie. The road to hell is paved with…
  • email
  • Print
  • Digg
  • Reddit
  • StumbleUpon
  • Google Bookmarks
  • del.icio.us
  • LinkedIn
  • Facebook
  • Twitter

How to make wordpress sidebars only appear on certain pages for search engine optimization

I was reading the recommendations in yoast.com’s post on wordpress seo.

Do you really need to link out to all your buddies in your blogroll site wide? Or is it perhaps wiser to just do that on your front page?

I want to link out on my homepage but I don’t need my sidebar to extend two screens below the content on my individual post pages.

So, it appears desirable to have elements of the sidebar (e.g. the blogroll and external social networking arcana) only appear on the homepage of my blog.

Thanks to some sample code from wpcandy.com, this was trivially easy to implement.

I modified the functions.php in my theme to register three sidebars. I called them Top Right Sidebar, Front Page Sidebar, and Bottom Right Sidebar.


if ( function_exists('register_sidebar') )
register_sidebar(array(
'name' => 'Top Right Sidebar',
'before_widget' => '', // Removes <li>
'after_widget' => '', // Removes </li>
'before_title' => '<h2>',
'after_title' => '</h2>',
));

if ( function_exists('register_sidebar') )
register_sidebar(array(
'name' => 'Front Page Sidebar',
'before_widget' => '', // Removes <li>
'after_widget' => '', // Removes </li>
'before_title' => '<h2>',
'after_title' => '</h2>',
));

if ( function_exists('register_sidebar') )
register_sidebar(array(
'name' => 'Bottom Right Sidebar',
'before_widget' => '', // Removes <li>
'after_widget' => '', // Removes </li>
'before_title' => '<h2>',
'after_title' => '</h2>',
));

Then I modified my sidebar.php to render those three sidebars if the dynamic_sidebar function exists also making the Front Page Sidebar conditional on is_front_page().

<?php
if ( function_exists('dynamic_sidebar') && dynamic_sidebar('Top Right Sidebar') ) : else :
?>
//default markup for the top sidebar goes here
<?php endif; ?>
//renders only if the current page is the front page, i.e. is_front_page()
<?php if ( function_exists('dynamic_sidebar') &&
is_front_page() && dynamic_sidebar('Front Page Sidebar') ) {} ?>
<?php
if ( function_exists('dynamic_sidebar') && dynamic_sidebar('Bottom Right Sidebar') ) : else :
?>
//default markup for the bottom sidebar goes here
<?php endif; ?>

Wordpress Widget Admin PageIn my widgets admin I now have three sidebars listed:

  • They are defined in my theme’s functions.php.
  • They render stacked one on top of the other based on the markup in sidebar.php.
  • I can populate them in the widget admin.
  • The middle bar only appears on the homepage.
  • email
  • Print
  • Digg
  • Reddit
  • StumbleUpon
  • Google Bookmarks
  • del.icio.us
  • LinkedIn
  • Facebook
  • Twitter

Merry Christmas

sledding-in-fort-greene-parkSledding in Fort Greene Park. Idyllic – when people aren’t sledding into light poles, fences, compost bins and other people.

  • email
  • Print
  • Digg
  • Reddit
  • StumbleUpon
  • Google Bookmarks
  • del.icio.us
  • LinkedIn
  • Facebook
  • Twitter

How to add an options form to a wordpress theme using settings_fields

I spent some time today modifying a WordPress theme to take configuration properties.

I want one theme that I can quickly re-configure to create multiple blogs along different topics with different color/graphic schemes. I want easy maintenance so I’d love to share one instance of the theme across these different instances.

We’re using enough different plugins that WordPress Mu isn’t yet worth fighting. So database options and the Settings API seemed the best way.

The documentation on how to extend a theme this way is not so easy to find but there are plenty of examples. They tend to break the process into steps but don’t give as much sense of what you actually get and how to use it.

I based my code on this example: http://blog.starscapetheme.com/2008/05/31/create-settings-page-for-theme/

After the fact, I found this description which seems well written: http://www.pixelace.com/2009/theme-options-for-wordpress-27/

I created a menu item and a corresponding properties form:

Wordpress Theme Options FormWordpress Theme Menu Item
 

My form adds three properties which are stored in the WordPress wp_options table and easily exposed on template pages

<link rel="stylesheet" href="<?php $options = get_option('vertical'); echo $options['vertical_custom_css_url']; ?>" type="text/css" media="screen" />

Here’s the actual code I added to the functions.php page of the theme. If you don’t have a functions.php you can just create one in your theme folder. You need to make sure the code below is wrapped in “<?php” “?>” tags.

//encapsulate the logic into a class
$cpanel = new ControlPanel();

class ControlPanel {
/* static array to contain default values
the values set an additional css to override standard css in the theme
as well as an image and link that is rendered in the sidebar. These
three settings allow me to use the same theme with minor variations
on different blogs on different topics but with very similar looks and feels */

var $default_settings = Array(
‘vertical_custom_css_url’ => ,
‘topic_banner_img’ => ‘/images/banner.jpg’,
‘topic_url’ => ‘http://www.judykat.com/ken’

);
//constructor
function ControlPanel()
{
//hook to add a menu item in the Theme’s area of the admin sidebar
add_action(‘admin_menu’, array(&$this, ‘vertical_admin_menu’));
/* if options are not already created in the database, add them and set to default values
this creates a single database entry in wp_options with key vertical and
values a hash of key/value pairs */

if (!is_array(get_option(‘vertical’)))
add_option(‘vertical’, $this->default_settings);
//load the existing options into an array accessible as a property of this instance of ControlPanel
$this->options = get_option(‘vertical’);
}
//the function that ties an html form to the hook defined in the constructor.
function vertical_admin_menu() {
add_theme_page(‘Vertical Theme Control Panel’, ‘Customize Theme’, ‘edit_themes’, “vertical”, array(&$this, ‘vertical_theme_page’));
}
//function that defines the form for viewing and setting properties for the theme.
function vertical_theme_page() {
//if the form is being submitted, update the options in the database
if ( isset( $_POST['submit'] ) ) {
//if the “Save Changes” button was clicked, set the user entered values from the form
if (‘Save Changes’ == $_POST['submit']) {
$this->options["vertical_custom_css_url"] = $_POST['vertical_custom_css_url'];
$this->options["topic_banner_img"] = $_POST['topic_banner_img'];
$this->options["topic_url"] = $_POST['topic_url'];
$state=“saved”;
} //else if “Defaults” was clicked, reset values to default
else if (‘Defaults’ == $_POST['submit']) {
$this->options["vertical_custom_css_url"] = $this->default_settings['vertical_custom_css_url'];
$this->options["topic_banner_img"] = $this->default_settings['topic_banner_img'];
$this->options["topic_url"] = $this->default_settings['topic_url'];
$state=“reverted to defaults”;
} //commit the changes to the database
update_option(‘vertical’, $this->options);
//render a status message of the above actions in the standard Wordpress admin dialog box at the top of the form.
echo ‘<div class=“updated fade” id=“message” style=“background-color: rgb(255, 251, 204); width: 300px; margin-left: 20px”><p>Settings <strong>‘.$state.’</strong>.</p></div>‘;
}
//the actual html form in standard markup to appear standard in the Wordpress Admin
?>
<div class=‘wrap’>
<h2><?php _e(‘Customize Vertical Theme’); ?></h2>
<div id=“header”>
<div id=“headwrap”>
<div id=“header”>
<div id=“headerimg”>
<h1><?php bloginfo(‘name’); ?></h1>
<div class=“description”><?php bloginfo(‘description’); ?></div>
</div>
</div>
</div>
</div>
<br>
<form id=“vertical-settings-form” method=“post” action=“”>
<?php settings_fields( ‘vertical-settings’ ); ?>
<table class=“form-table”>
<tr valign=“top”>
<th scope=“row”>Path to Vertical CSS file:</th>
<td>
<input size=“70″ type=“text” name=“vertical_custom_css_url” id=“vertical_custom_css_url” value=<?php echo $this->options["vertical_custom_css_url"]; ?>” />
<br/><small>example: <?php echo(str_replace(get_bloginfo(‘url’),“”,get_bloginfo(‘template_url’).‘/’.str_replace(” “, “-”,strtolower(wptexturize(get_bloginfo( ‘name’ )))))); ?>/style.css</small>
</td>
</tr>
<tr valign=“top”>
<th scope=“row”>Path to Category Page:</th>
<td>
<input size=“70″ type=“text” name=“topic_url” id=“topic_url” value=<?php echo $this->options["topic_url"]; ?>” />
<br/><small>example: http://www.judykat.com/ken</small>
</td>
</tr>
<tr valign=“top”>
<th scope=“row”>Path to Category Banner:</th>
<td>
<input size=“70″ type=“text” name=“topic_banner_img” id=“topic_banner_img” value=<?php echo $this->options["topic_banner_img"]; ?>” />
<br/><small>example: <?php echo(str_replace(get_bloginfo(‘url’),“”,get_bloginfo(‘template_url’).‘/’.str_replace(” “, “-”,strtolower(wptexturize(get_bloginfo( ‘name’ )))))); ?>/images/banner.jpg</small>
</td>
</tr>
</table>
<p class=“submit”>
<input type=“submit” name=“submit” class=“button-primary” value=<?php _e(‘Save Changes’) ?> />
<input type=“submit” name=“submit” class=“button-primary” value=<?php _e(‘Defaults’) ?> />
</p>
<input type=“hidden” name=“saved” value=“true”>
</form>
</div>
<?php
}
}

  • email
  • Print
  • Digg
  • Reddit
  • StumbleUpon
  • Google Bookmarks
  • del.icio.us
  • LinkedIn
  • Facebook
  • Twitter

Please note: there is no candy in this store

There is no candy in this store


PLEASE NOTE:

There is NO CANDY in this store

All minors must be accompanied by an adult at all times.

If any product is broken by minor for any reason, product must be reimbursed to the store.

Thank you for your cooperation.

Seen at a Seattle mall during an advertised halloween event.

  • email
  • Print
  • Digg
  • Reddit
  • StumbleUpon
  • Google Bookmarks
  • del.icio.us
  • LinkedIn
  • Facebook
  • Twitter

Power, dissent, and bullying in software developer communities

Grassroots developer communities form around shared values in dissent against institutions and norms that dehumanize their work and diminish their efforts. They attack these orthodoxies with humor, heretical thinking, and hard work.

This benefits society when developers defy those with greater power. It harms society when developers bully people with less power.

At the ThoughtWorks sponsored Agile East, Martin Fowler spoke to his post, SmutOnRails.

Part of the community was offended by a presentation at the GoGaRuCo (Golden Gate Ruby Conference). Others fought back saying that no offense was meant, the presenter apologized, and that the tone was in the spirit of the Rails community.

(T)he view of the rails leadership seems to be this: that the objections to the presentation are yet another attempt to foist empty corporate values on the thriving Rails ecosystem… (more)

This debate is not unique to the Rails community. It reminds me of concerns my friend, Luke Melia, raised over jokes and behavior at the first Austin Alt.NET. Martin Fowler links off to a similar controversy in the Flash community.

It is also not unique to developer communities but developers in particular need to be concerned about the outcome.

Women, African Americans and Hispanics are under-represented in IT and even more so in software development. In 2001-2002 74.4% of software developers were men. 78% of those men were white.

In 1986 the percentage of women in CS programs peaked at 37%. The percentage of women in computer science programs has gone down since then.

In 2001-2, only 28 percent of all undergraduate degrees in computer science went to women. By 2004-5, the number had declined to only 22 percent. — What Has Driven Women Out of Computer Science?, NY Times

There were 15,000 women in CS progreams in 1986. Riding natural cycles this number was not matched again until 2003. This latter number contains a higher percentage of non-resident aliens who will not necessarily contribute to the US workforce.

This despite higher percentages and numbers of women acquiring college educations than men. In 2007, 33% of women 25-29 held a four year degree or higher versus 26% of men. 55% of graduates with four year degrees or higher aged 25-29 were women.

Women are even receiving the majority of degrees in science and technology. They have shown steady progress in biology, chemistry, physics, mathematics and engineering.

Metrics can be misinterpreted but these quantitative measures support a stunningly obvious anecdotal observation. US software developers are a white male enclave.

This is a power imbalance and we developers are part of the problem.

Isolation is a key factor for a higher attrition rate among women and minorities, said Teresa Dahlberg, director of the Diversity in Information Technology Institute at UNC Charlotte. People tend to associate with “like communities,” where people have similar backgrounds and interests, she explained. — Computer science lacks women, minorities, SD Times

So when we behave in a way that marginalizes and intimidates talented women and minorities, we abuse power. We become bullies. We are oppressors.

“There is a good amount of research that shows that women are judged more harshly than men, for hiring, evaluations and promotions,” she added. “Virginia Valian [author of "Why So Slow? The Advancement of Women"] shows this for women in science, technology, engineering and math faculty jobs.” Virginia Valian is a professor at Hunter College. — SD Times

Part of the problem may be a perception that software development doesn’t contribute enough to society. To the degree this perception is true it is damning. To the degree it is just a perception we have work to do as advocates.

Our actions need to be judged not by our intentions but by the outcome.

Requisite variety within our teams remains an essential enabling condition for sustained innovation.

Access to technology is growing across all tiers of class, race and gender both in the US and overseas. Diverse teams can better address our market and build software better adapted to our end users.

A more diverse workforce provides the kind of social change that will help us create a more humane workplace for developers.

Finally, anything that limits the number of able US software developers hurts our ability to compete.

When developer communities marginalize women and minorities, we conspire to isolate ourselves from the larger society. We defeat our own attempts to change the power structures around us and improve our lot and our output.

  • email
  • Print
  • Digg
  • Reddit
  • StumbleUpon
  • Google Bookmarks
  • del.icio.us
  • LinkedIn
  • Facebook
  • Twitter
1 2 3 4 5 6 7 8 9 10 ... 25 26   Next Page »
ken h. judyExecutive manager, software developer, father and husband trying to do more good than harm.
Agile is about the material and human good we create when we respect our co-workers, tell truth to our employers, strive to improve, and care for the people affected by the software we help build.
CSPIEEE CSDP

Papers

Presentations

 

Tags

Affiliations

tallman by miya judy

What I'm Doing...

  • I turned on the tap for click feature on my trackpad because I'm just that kind of risk taker. 1 week ago
  • Playing the game of life and watching the how it's made marathon has given me ennui. 1 week ago
  • Instead of writing to a mount, superduper copied my drive into a directory in /Volumes named the same as the mount. Sneaky disk full fail. 1 week ago
  • It's not going to extend my life any but in project crunch sometimes you need a little chinese-american takeout. 2 weeks ago
  • Troubleshooting an old site on an old server. As the ma bell guy said when the line stopped working, "Someone did something to something." 2 weeks ago
  • More updates...

Posting tweet...

Powered by Twitter Tools

Shelfari: Book reviews on your book blog
Shelfari: Book reviews on your book blog

Meta

Creative Commons License
This work is licensed under a Creative Commons Attribution - Noncommercial - Share Alike 3.0 United States License.
Copyright © 2006-2010
Ken H. Judy.
This is a personal weblog. Views expressed are my own and not my employer.