<?xml version="1.0"?>
<News hasArchived="true" page="7640" pageCount="10791" pageSize="10" timestamp="Fri, 04 Sep 2026 11:28:37 -0400" url="https://my3.my.umbc.edu/posts.xml?mode=activity&amp;page=7640&amp;range=2">
<NewsItem contentIssues="true" id="43334" important="false" status="posted" url="https://my3.my.umbc.edu/posts/43334">
<Title>Proposed Merger Would Enhance Competition, Say Comcast and Time Warner Cable</Title>
<Body>
<![CDATA[
    <div class="html-content">The companies filed documents in support of the plan, which has faced opposition and will be the subject of a Senate hearing this week.<br><br><br><a href="http://da.feedsportal.com/r/194479879666/u/0/f/640387/c/34625/s/391ff879/sc/1/rc/1/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479879666/u/0/f/640387/c/34625/s/391ff879/sc/1/rc/1/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/194479879666/u/0/f/640387/c/34625/s/391ff879/sc/1/rc/2/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479879666/u/0/f/640387/c/34625/s/391ff879/sc/1/rc/2/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/194479879666/u/0/f/640387/c/34625/s/391ff879/sc/1/rc/3/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479879666/u/0/f/640387/c/34625/s/391ff879/sc/1/rc/3/rc.img" style="max-width: 100%; height: auto;"></a><br><br><a href="http://da.feedsportal.com/r/194479879666/u/0/f/640387/c/34625/s/391ff879/sc/1/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479879666/u/0/f/640387/c/34625/s/391ff879/sc/1/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>The companies filed documents in support of the plan, which has faced opposition and will be the subject of a Senate hearing this week.</Summary>
<Website>http://rss.nytimes.com/c/34625/f/640387/s/391ff879/sc/1/l/0L0Snytimes0N0C20A140C0A40C0A90Cbusiness0Cmedia0Cproposed0Emerger0Ewould0Eenhance0Ecompetition0Esay0Ecomcast0Eand0Etime0Ewarner0Ecable0Bhtml0Dpartner0Frss0Gemc0Frss/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/43334/guest@my.umbc.edu/f61e9e73b67896ec48b493471862c204/api/pixel</TrackingUrl>
<Tag>amazon-com-inc-amzn-nasdaq</Tag>
<Tag>antitrust-laws-and-competition-issues</Tag>
<Tag>apple-inc-aapl-nasdaq</Tag>
<Tag>at-and-t-inc-t-nyse</Tag>
<Tag>cable-television</Tag>
<Tag>comcast-corporation-cmcsa-nasdaq</Tag>
<Tag>computers-and-the-internet</Tag>
<Tag>facebook-inc-fb-nasdaq</Tag>
<Tag>federal-communications-commission</Tag>
<Tag>google-inc-googl-nasdaq</Tag>
<Tag>mergers-acquisitions-and-divestitures</Tag>
<Tag>netflix-inc-nflx-nasdaq</Tag>
<Tag>new</Tag>
<Tag>senate-committee-on-the-judiciary</Tag>
<Tag>technology</Tag>
<Tag>telephones-and-telecommunications</Tag>
<Tag>time-warner-cable-inc-twc-nyse</Tag>
<Tag>time-warner-inc-twx-nyse</Tag>
<Tag>verizon-communications-inc-vz-nyse</Tag>
<Tag>yahoo-inc-yhoo-nasdaq</Tag>
<Tag>york</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 08 Apr 2014 10:00:08 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="43331" important="false" status="posted" url="https://my3.my.umbc.edu/posts/43331">
<Title>Font Size Idea: px at the Root, rem for Components, em for Text Elements</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p>Me, for the last year or so: "<code>rem</code>'s are so cool! I'm gonna size everything with them, that way I can adjust the font-size on the root element and everything will scale with it!" It was a nice dream. And it wasn't a disaster.  That's what I'm doing right now here on CSS-Tricks and this is how it plays out in a very simple scenario:</p>
    <img src="http://cdn.css-tricks.com/wp-content/uploads/2014/04/rem-all.png" alt="" style="max-width: 100%; height: auto;">
    <p>That comes from essentially:</p>
    <pre><code>/* Document level adjustments */&#x000A;    html {&#x000A;      font-size: 17px;&#x000A;    }&#x000A;    @media (max-width: 900px) {&#x000A;      html { font-size: 15px; }&#x000A;    }&#x000A;    @media (max-width: 400px) {&#x000A;      html { font-size: 13px; }&#x000A;    }&#x000A;    &#x000A;    /* Type will scale with document */&#x000A;    h1 {&#x000A;      font-size: 3rem;&#x000A;    }&#x000A;    h2 {&#x000A;      font-size: 2.5rem;&#x000A;    }&#x000A;    h3 {&#x000A;      font-size: 2rem;&#x000A;    }</code></pre>
    <p>I admit that I like that simplicity, but I'm starting to think it's a little too dreamy for all but the simplest of sites. The main issue: you just can't expect type that you set at one screen size to look just right by simply scaling it down entirely proportionally. Big type might get too big scaling up. Small type might get too small (a common one that gets me). Or even the reverse of either, where big type might not get small <em>enough</em>. </p>
    <p>If any of those things happen, then you're making @media query specific adjustments which not only gets confusing but isn't very efficient (adjusting size just to adjust it again to fix it). </p>
    <p>So here's my idea: you still keep <code>px</code> size adjustments at the document level so you can make easy/efficient sweeping size changes. But then each module on the page has a font-size set in <code>rem</code>. Actual text elements (h1, h2, p, li, whatever), if you size them at all, are sized in em, and thus become relative to the module.</p>
    <p>This way you can adjust font-size at a module level, which is pretty easy. The chances the type within a single module have good proportions and can scale together nicely is high. So that would play out like this:</p>
    <img src="http://cdn.css-tricks.com/wp-content/uploads/2014/04/layout.svg" alt="" style="max-width: 100%; height: auto;"><br>
    Not to scale. Just showing what units would go on what.<br>
    
    <p>You can play around with the idea here by adjusting the sliders:</p>
    <p>See the Pen <a href="http://codepen.io/chriscoyier/pen/tvheK/" rel="nofollow external" class="bo">Em AND Rem</a> by Chris Coyier (<a href="http://codepen.io/chriscoyier" rel="nofollow external" class="bo">@chriscoyier</a>) on <a href="http://codepen.io" rel="nofollow external" class="bo">CodePen</a>.</p>
    <p>At a certain medium size, everything looks fine. Scaling up, you can get to a point where the main articles are a good big size, but the sidebar stuff doesn't need to be that big. With this system it would be easy to target them and notch them back down. Scaling down, those sidebar modules get a bit too small too fast, so you could notch them back up easily. There might even be sizes where you equalize things because you've gone single column (or the like).</p>
    <p>This is how it would go down:</p>
    <pre><code>/* Document level adjustments */&#x000A;    html {&#x000A;      font-size: 17px;&#x000A;    }&#x000A;    @media (max-width: 900px) {&#x000A;      html { font-size: 15px; {&#x000A;    }&#x000A;    @media (max-width: 400px) {&#x000A;      html { font-size: 13px; }&#x000A;    }&#x000A;    &#x000A;    /* Modules will scale with document */&#x000A;    .header {&#x000A;      font-size: 1.5rem;&#x000A;    }&#x000A;    .footer {&#x000A;      font-size: 0.75rem;&#x000A;    }&#x000A;    .sidebar {&#x000A;      font-size: 0.85rem;&#x000A;    }&#x000A;    &#x000A;    /* Type will scale with modules */&#x000A;    h1 {&#x000A;      font-size: 3em;&#x000A;    }&#x000A;    h2 {&#x000A;      font-size: 2.5em;&#x000A;    }&#x000A;    h3 {&#x000A;      font-size: 2em;&#x000A;    }</code></pre>
    <p>I put "idea" in the title because I haven't actually built a site doing this yet, but it makes sense to me and I'd surely try it.</p>
    <hr>
    <p><small><a href="http://css-tricks.com/rems-ems/" rel="nofollow external" class="bo">Font Size Idea: px at the Root, rem for Components, em for Text Elements</a> is a post from <a href="http://css-tricks.com" rel="nofollow external" class="bo">CSS-Tricks</a></small></p>
    </div>
]]>
</Body>
<Summary>Me, for the last year or so: "rem's are so cool! I'm gonna size everything with them, that way I can adjust the font-size on the root element and everything will scale with it!" It was a nice...</Summary>
<Website>http://css-tricks.com/rems-ems/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/43331/guest@my.umbc.edu/4a1d013539eb9f29b6808bd9a73dbb6a/api/pixel</TrackingUrl>
<Tag>article</Tag>
<Tag>css</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>tricks</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 08 Apr 2014 09:33:23 -0400</PostedAt>
<EditAt>Tue, 08 Apr 2014 09:33:23 -0400</EditAt>
</NewsItem>

<NewsItem contentIssues="false" id="43356" important="false" status="posted" url="https://my3.my.umbc.edu/posts/43356">
<Title>PatientsLikeMe Gives Genentech Full Access</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p>The most extensive collaboration between the patient social network and a drug company to-date is likely to be just the first of its kind.</p>
    <p><span>PatientsLikeMe, the largest online network for patients, has established its first broad partnership with a drug company. Genentech, the South San Francisco biotechnology company bought by Roche in 2009, now has access to<span> </span><a href="http://news.patientslikeme.com/press-release/genentech-and-patientslikeme-enter-patient-centric-research-collaboration" rel="nofollow external" class="bo"><span>PatientsLikeMe’s full database for five years</span></a>.</span></p>
    </div>
]]>
</Body>
<Summary>The most extensive collaboration between the patient social network and a drug company to-date is likely to be just the first of its kind.  PatientsLikeMe, the largest online network for patients,...</Summary>
<Website>http://www.technologyreview.com/view/526266/patientslikeme-gives-genentech-full-access/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/43356/guest@my.umbc.edu/c39f64905e09405680c7b3be6a5e1774/api/pixel</TrackingUrl>
<Tag>development</Tag>
<Tag>internet</Tag>
<Tag>mit</Tag>
<Tag>technology</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 08 Apr 2014 09:05:26 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="43329" important="false" status="posted" url="https://my3.my.umbc.edu/posts/43329">
<Title>Two Fall Courses on Leadership &amp; Social Change</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <span>by David Hoffman</span><br><div>
    <div>
    <span><br></span><span>If you're interested in building your skills as a leader and agent of positive social change ... well, you've chosen the right university, because there are <a href="http://umbcbreakingground.wordpress.com/" rel="nofollow external" class="bo">plenty of opportunities</a>. I'm going to highlight just two of many fall courses that may appeal to you.</span>
    </div>
    <div>
    <span><br></span><strong><span>Civic Agency &amp; Social Entrepreneurship (AMST 205/POLI 205/SOCY 205)</span></strong>
    </div>
    <div>
    <span><br></span><em><span>Instructors: David Hoffman and Craig Berger (your Co-Create UMBC authors)</span></em>
    </div>
    <div><em><span>3 credits</span></em></div>
    <div><em><span>TuTh 11:30-12:45</span></em></div>
    <div>
    <span><span><br></span></span><span><span>Students in this highly interactive, discussion-focused course will explore the process of social change through reading, conversations and hands-on group work. Bring your desire to make a positive difference; we'll help you identify your passions and channel your hopes into practical projects at UMBC. </span></span><br><span><span><br></span></span><span><span>Projects designed by students in previous semesters have included putting up <a href="http://umbcbreakingground.wordpress.com/2014/02/20/new-statues-show-retriever-colors/" rel="nofollow external" class="bo">fiberglass Retriever statues</a> around campus with designs reflecting UMBC's values and diversity, setting up new applied research opportunities for UMBC undergraduates, developing new health and wellness resources for UMBC students, installing hydration stations to discourage bottled water use on campus (the first of these was installed in the Retriever Learning Center), and <a href="http://www.retrieverweekly.com/technology/yohka-tanaka-conducts-research-into-social-reform-1.3018469#.UVs25ResiSo" rel="nofollow external" class="bo">expanding campus food options</a>. Learning how to get a real project off the ground can be a challenge, but the payoff is that you will develop the confidence and perspective you need to succeed as an agent of change.</span></span>
    </div>
    <div>
    <span><br><span>Just like in previous semesters, we plan to engage exciting guests to help you build your skills and hone your ideas. </span><span>If you have questions about this course, feel free to email me (David Hoffman, <a href="mailto:dhoffman@umbc.edu">dhoffman@umbc.edu</a>).</span></span><br><span><span><br></span></span><br><div><strong><span>Foundations of Leadership Development (EDUC 216/PSYC 216)</span></strong></div>
    <div>
    <span><br></span><em><span>Instructors: Virginia Byrne and Lee Calizo</span></em>
    </div>
    <div><em><span>3 credits</span></em></div>
    <div><em><span>W 4:30-7:00</span></em></div>
    <div><em><span><br></span></em></div>
    <div><span>This course is designed to help develop effective, ethical leaders. <span> As UMBC student you can interact with and influence other UMBC students on a daily basis.  This course is designed to help you to develop as a leader and to prepare you to have a positive influence on others at UMBC and throughout your life.  Through experiential projects and theoretical readings, this course will provide a foundation for your leadership development.</span></span></div>
    <div><span><br><span>Example of how this course differs from other courses:</span><br><br><span>1) Class participation focused: </span><span>Leadership is an inherently relational process.  Within this course, you will share the responsibility to create a dynamic learning environment in which you will have the opportunity to understand, acquire, practice, reflect, and apply leadership knowledge, skills, and values. Each member of the class will be an expert in his or her own personal experience and how that experience informs and shapes the meaning made from course readings.  </span><br><br><span>2) Many right answers about leadership: You will not leave this class with a 12 step plan for becoming a superhero, but you will practice skills that will help you make a difference in your community and improve your relationships.</span><br><br><span>3) No PowerPoint presentations. At all.</span></span></div>
    <div>
    <span><br></span><span><span>If you have questions about this course, email Virginia Byrne: <a href="mailto:vbyrne@umbc.edu" rel="nofollow external" class="bo">vbyrne@umbc.edu</a>. </span>Find Virginia on Twitter at @WeLeadUMBC and on myUMBC at <a href="http://my.umbc.edu/groups/lc" rel="nofollow external" class="bo">http://my.umbc.edu/groups/lc</a>.</span>
    </div>
    <div>
    <span><br></span><em><a href="http://cocreateumbc.blogspot.com/" rel="nofollow external" class="bo">Co-Create UMBC</a> is a blog for and about UMBC, written by David Hoffman and Craig Berger from the Office of Student Life. Join the <a href="http://my.umbc.edu/groups/co-create" rel="nofollow external" class="bo">Co-Create UMBC group</a> on MyUMBC. Like <a href="https://www.facebook.com/cocreateumbc" rel="nofollow external" class="bo">Co-Create UMBC on Facebook</a>. And follow <a href="https://twitter.com/CoCreateUMBC" rel="nofollow external" class="bo">David</a> and <a href="https://twitter.com/CraigBerger" rel="nofollow external" class="bo">Craig</a> on Twitter.</em><span> </span>
    </div>
    </div>
    </div>
    </div>
]]>
</Body>
<Summary>by David Hoffman    If you're interested in building your skills as a leader and agent of positive social change ... well, you've chosen the right university, because there are plenty of...</Summary>
<Website>http://cocreateumbc.blogspot.com/2014/04/two-fall-courses-on-leadership-social.html</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/43329/guest@my.umbc.edu/d691eeda354f969a56dd2ed0cbb2d955/api/pixel</TrackingUrl>
<Tag>social-entrepreneurship-course</Tag>
<Group token="co-create">Co-Create UMBC</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/co-create</GroupUrl>
<AvatarUrl>https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/002/5b8f025dafb56cb8d3088b7259aadcfb/xsmall.png?1499890363</AvatarUrl>
<AvatarUrl size="original">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/002/5b8f025dafb56cb8d3088b7259aadcfb/original.jpg?1499890363</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/002/5b8f025dafb56cb8d3088b7259aadcfb/xxlarge.png?1499890363</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/002/5b8f025dafb56cb8d3088b7259aadcfb/xlarge.png?1499890363</AvatarUrl>
<AvatarUrl size="large">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/002/5b8f025dafb56cb8d3088b7259aadcfb/large.png?1499890363</AvatarUrl>
<AvatarUrl size="medium">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/002/5b8f025dafb56cb8d3088b7259aadcfb/medium.png?1499890363</AvatarUrl>
<AvatarUrl size="small">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/002/5b8f025dafb56cb8d3088b7259aadcfb/small.png?1499890363</AvatarUrl>
<AvatarUrl size="xsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/002/5b8f025dafb56cb8d3088b7259aadcfb/xsmall.png?1499890363</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/002/5b8f025dafb56cb8d3088b7259aadcfb/xxsmall.png?1499890363</AvatarUrl>
<Sponsor>Co-Create UMBC</Sponsor>
<PawCount>48</PawCount>
<CommentCount>5</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 08 Apr 2014 08:59:00 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="43328" important="false" status="posted" url="https://my3.my.umbc.edu/posts/43328">
<Title>DealBook: Box Chief Invests in Supply Chain Software Company</Title>
<Body>
<![CDATA[
    <div class="html-content">With ambitions of changing supply chain management, a start-up called Elementum has raised $5 million from technology entrepreneurs.<br><br><br><a href="http://da.feedsportal.com/r/194479861772/u/0/f/640387/c/34625/s/391e7441/sc/15/rc/1/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479861772/u/0/f/640387/c/34625/s/391e7441/sc/15/rc/1/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/194479861772/u/0/f/640387/c/34625/s/391e7441/sc/15/rc/2/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479861772/u/0/f/640387/c/34625/s/391e7441/sc/15/rc/2/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/194479861772/u/0/f/640387/c/34625/s/391e7441/sc/15/rc/3/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479861772/u/0/f/640387/c/34625/s/391e7441/sc/15/rc/3/rc.img" style="max-width: 100%; height: auto;"></a><br><br><a href="http://da.feedsportal.com/r/194479861772/u/0/f/640387/c/34625/s/391e7441/sc/15/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479861772/u/0/f/640387/c/34625/s/391e7441/sc/15/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>With ambitions of changing supply chain management, a start-up called Elementum has raised $5 million from technology entrepreneurs.</Summary>
<Website>http://rss.nytimes.com/c/34625/f/640387/s/391e7441/sc/15/l/0Ldealbook0Bnytimes0N0C20A140C0A40C0A80Cbox0Echief0Einvests0Ein0Esupply0Echain0Esoftware0Ecompany0C0Dpartner0Frss0Gemc0Frss/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/43328/guest@my.umbc.edu/8e1b7ad0c77743564b2a34c973b6a824/api/pixel</TrackingUrl>
<Tag>basic-materials</Tag>
<Tag>box-inc</Tag>
<Tag>cloud-computing</Tag>
<Tag>computers-and-the-internet</Tag>
<Tag>dyson</Tag>
<Tag>i-p-o-offerings</Tag>
<Tag>levie-aaron-w</Tag>
<Tag>new</Tag>
<Tag>technology</Tag>
<Tag>workday-inc</Tag>
<Tag>workday-inc-wday-nyse</Tag>
<Tag>york</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 08 Apr 2014 08:04:32 -0400</PostedAt>
<EditAt>Wed, 09 Apr 2014 09:17:59 -0400</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="43335" important="false" status="posted" url="https://my3.my.umbc.edu/posts/43335">
<Title>DealBook Column: Tech Firms May Find No-Poaching Pacts Costly</Title>
<Body>
<![CDATA[
    <div class="html-content">Employees of technology companies have filed a class-action lawsuit that contends that illegal hiring practices among their companies has cost them billions in lost wages.<br>
    </div>
]]>
</Body>
<Summary>Employees of technology companies have filed a class-action lawsuit that contends that illegal hiring practices among their companies has cost them billions in lost wages.</Summary>
<Website>http://rss.nytimes.com/c/34625/f/640387/s/391ff874/sc/30/l/0Ldealbook0Bnytimes0N0C20A140C0A40C0A70Ctech0Efirms0Emay0Efind0Eno0Epoaching0Epacts0Ecostly0C0Dpartner0Frss0Gemc0Frss/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/43335/guest@my.umbc.edu/e8eb71613ca77a665f81c3c40dff2828/api/pixel</TrackingUrl>
<Tag>antitrust-laws-and-competition-issues</Tag>
<Tag>apple-inc</Tag>
<Tag>apple-inc-aapl-nasdaq</Tag>
<Tag>dealbook-column</Tag>
<Tag>google-inc</Tag>
<Tag>google-inc-googl-nasdaq</Tag>
<Tag>hiring-and-promotion</Tag>
<Tag>jobs-steven-p</Tag>
<Tag>justice-department</Tag>
<Tag>new</Tag>
<Tag>schmidt-eric-e</Tag>
<Tag>silicon-valley-calif</Tag>
<Tag>suits-and-litigation-civil</Tag>
<Tag>technology</Tag>
<Tag>top-headline-1</Tag>
<Tag>york</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 08 Apr 2014 07:32:03 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="43342" important="false" status="posted" url="https://my3.my.umbc.edu/posts/43342">
<Title>Samsung Electronics Hit by Earnings Decline as Smartphone Sales Slow</Title>
<Body>
<![CDATA[
    <div class="html-content">The world’s biggest smartphone maker is rolling out the fifth version of its Galaxy S smartphone, but it has received mixed reviews.<br>
    </div>
]]>
</Body>
<Summary>The world’s biggest smartphone maker is rolling out the fifth version of its Galaxy S smartphone, but it has received mixed reviews.</Summary>
<Website>http://rss.nytimes.com/c/34625/f/640387/s/3921cf4d/sc/15/l/0L0Snytimes0N0C20A140C0A40C0A90Cbusiness0Cinternational0Csamsung0Eelectronics0Ehit0Eby0Eearnings0Edecline0Eas0Esmartphone0Esales0Eslow0Bhtml0Dpartner0Frss0Gemc0Frss/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/43342/guest@my.umbc.edu/29451e7e22960532dc34310cbe75be55/api/pixel</TrackingUrl>
<Tag>new</Tag>
<Tag>technology</Tag>
<Tag>york</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 08 Apr 2014 06:52:25 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="43327" important="false" status="posted" url="https://my3.my.umbc.edu/posts/43327">
<Title>How To Build A Ruby Gem With Bundler, Test-Driven Development, Travis CI And Coveralls, Oh My!</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <table width="650">
    <tbody>
    <tr>
    <td>
    <div>
    <img src="http://statisches.auslieferung.commindo-media-ressourcen.de/advertisement.gif" alt="" style="max-width: 100%; height: auto;"><br><a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=1" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=1" alt="" style="max-width: 100%; height: auto;"></a> <a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=2" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=2" alt="" style="max-width: 100%; height: auto;"></a> <a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=3" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=3" alt="" style="max-width: 100%; height: auto;"></a>
    </div>
    </td>
    </tr>
    </tbody>
    </table>
    <p>Ruby is a great language. It was designed to foster happiness and productivity in developers, all the while providing tools that are effective and yet focused on simplicity. One of the tools available to the Rubyist is the <a href="http://rubygems.org/" rel="nofollow external" class="bo">RubyGems</a> package manager. It enables us both to include “gems” (i.e. packaged code) that we can reuse in our own applications and to package our own code as a gem to share with the <a href="https://www.ruby-lang.org/" rel="nofollow external" class="bo">Ruby</a> community. We’ll be focusing on the latter in this article.</p>
    <p>I’ve written an open-source gem named <a href="https://rubygems.org/gems/sinderella" rel="nofollow external" class="bo">Sinderella</a> (<a href="https://github.com/Integralist/Sinderella" rel="nofollow external" class="bo">available on GitHub</a>), and in this article I’ll go through all of the steps I took to write the code (including the <a href="http://en.wikipedia.org/wiki/Test_driven_development" rel="nofollow external" class="bo">test-driven development</a> process) and how I prepared it for release as a gem via RubyGems. I’ll also show you how to set up your tests to run through a <a href="http://en.wikipedia.org/wiki/Continuous_integration" rel="nofollow external" class="bo">continuous integration</a> (CI) server using the popular <a href="https://travis-ci.org/" rel="nofollow external" class="bo">Travis CI</a> service.</p>
    <p>In case you’re unfamiliar with CI, it refers to the process of merging code with a central repository, with the aim of preventing integration problems down the road in a project’s life cycle. (If you use a version control system such as <a href="http://git-scm.com/" rel="nofollow external" class="bo">git</a> and a decentralized code repository such as <a href="https://github.com/" rel="nofollow external" class="bo">GitHub</a>, then you might already be familiar with these concepts.)</p>
    <p>Finally, I’ll show you how to use <a href="https://coveralls.io/" rel="nofollow external" class="bo">Coveralls</a> to measure the code coverage of your tests and to obtain a statistical history of your commits.</p>
    <p><img src="http://media.smashingmagazine.com/wp-content/uploads/2014/04/Ruby-Bundler-Travis-CI-opt.png" width="500" height="263" style="max-width: 100%; height: auto;"><br><em>Image credit: The <a href="https://www.ruby-lang.org/en/" rel="nofollow external" class="bo">Ruby</a> and <a href="http://bundler.io/" rel="nofollow external" class="bo">Bundler</a> logos, along with the <a href="https://travis-ci.org/" rel="nofollow external" class="bo">Travis CI</a> mascot.</em></p>
    <h4>What We’ll Cover</h4>
    <ul>
    <li><a href="#a1" rel="nofollow external" class="bo">What does Sinderella do?</a></li>
    <li><a href="#a2" rel="nofollow external" class="bo">What we won’t cover</a></li>
    <li><a href="#a3" rel="nofollow external" class="bo">Additional requirements</a></li>
    <li><a href="#a4" rel="nofollow external" class="bo">Which version of Ruby to use</a></li>
    <li><a href="#a5" rel="nofollow external" class="bo">Bundler</a></li>
    <li><a href="#a6" rel="nofollow external" class="bo">Dependencies</a></li>
    <li><a href="#a7" rel="nofollow external" class="bo">Generating a boilerplate</a></li>
    <li><a href="#a8" rel="nofollow external" class="bo">Test-driven development</a></li>
    <li><a href="#a9" rel="nofollow external" class="bo">RSpec</a></li>
    <li><a href="#a10" rel="nofollow external" class="bo">Guard and tmux</a></li>
    <li><a href="#a11" rel="nofollow external" class="bo">Continuous integration with Travis CI</a></li>
    <li><a href="#a12" rel="nofollow external" class="bo">Code coverage and statistics with Coveralls.io</a></li>
    <li><a href="#a13" rel="nofollow external" class="bo">Skeleton specification</a></li>
    <li><a href="#a14" rel="nofollow external" class="bo">Design patterns</a></li>
    <li><a href="#a15" rel="nofollow external" class="bo">Badges</a></li>
    <li><a href="#a16" rel="nofollow external" class="bo">REPL-driven development</a></li>
    <li><a href="#a17" rel="nofollow external" class="bo">Releasing your gem</a></li>
    <li><a href="#a18" rel="nofollow external" class="bo">Conclusion</a></li>
    </ul>
    <h3>What Does Sinderella Do?</h3>
    <p>As described in the README on GitHub, Sinderella allows the author to “pass a code block to transform a data object for a specific period of time.” So, if we provide data like the following…</p>
    <pre><code>&#x000A;    { :key =&gt; 'value' }&#x000A;    </code></pre>
    <p>… then we could, for example, convert it to the following for a set period of time:</p>
    <pre><code>&#x000A;    { :key =&gt; 'VALUE' }&#x000A;    </code></pre>
    <p>Once the time period has expired, the data is returned to its normal state.</p>
    <p>Sinderella is made up of two files: the main application and a data store that holds the original and transformed data.</p>
    <p>Later in this article, I’ll describe my development process for creating the gem, and we’ll review some of the techniques required to produce a robust and stable gem.</p>
    <h3>What We Won’t Cover</h3>
    <p>To be clear, this article is focused on creating a Ruby gem using Bundler and on following best practices, such as test-driven development and CI.</p>
    <p>We won’t cover how to write Ruby code or how we developed the Sinderella gem. Nor will we cover how to write RSpec tests (although we will demonstrate how to set up RSpec). RSpec is a detail of implementation and can be swapped out for any testing library that you deem appropriate.</p>
    <h3>Additional Requirements</h3>
    <p>To get started, you’ll need to register for accounts with the following services:</p>
    <ul>
    <li><a href="https://travis-ci.org/" rel="nofollow external" class="bo">Travis CI</a></li>
    <li><a href="https://rubygems.org/" rel="nofollow external" class="bo">RubyGems</a></li>
    <li><a href="https://coveralls.io/" rel="nofollow external" class="bo">Coveralls</a></li>
    </ul>
    <p>Registering for these services is free. Travis CI is free for all open-source projects (which this will be). You may pay for a Pro account, which allows you to set up CI for your private code repositories, but that’s not needed for what we’ll be doing here.</p>
    <p>You’ll also need to be comfortable working in the command line. You don’t have to be a Unix shell scripting wizard, but I’ll be working here exclusively in a shell environment (specifically, using the <a href="http://en.wikipedia.org/wiki/Terminal_(OS_X" rel="nofollow external" class="bo">Terminal</a> on Mac OS X) to do everything, including running shell commands, opening multiplexers (such as <a href="http://en.wikipedia.org/wiki/Tmux" rel="nofollow external" class="bo">tmux</a>) and editing code (with <a href="http://www.integralist.co.uk/posts/a-guide-to-getting-started-with-vim/" rel="nofollow external" class="bo">Vim</a>).</p>
    <h3>Which Version Of Ruby To Use</h3>
    <p>Ruby has many different flavors:</p>
    <ul>
    <li>
    <a href="http://ruby-lang.org/" rel="nofollow external" class="bo">Ruby</a> (also known as Matz’s Ruby Interpreter) is the original language, written in C.</li>
    <li>
    <a href="http://rubini.us/" rel="nofollow external" class="bo">Rubinius</a> is an implementation of Ruby that is written mainly with Ruby.</li>
    <li>
    <a href="http://jruby.org/" rel="nofollow external" class="bo">JRuby</a> is an implementation of Ruby built on top of the Java Virtual Machine (JVM), with Java.</li>
    </ul>
    <p>I deliberately used JRuby to implement Sinderella because part of the gem’s code relies on “<a href="http://en.wikipedia.org/wiki/Multi-threaded" rel="nofollow external" class="bo">threads</a>,” and MRI doesn’t provide true threading.</p>
    <p>JRuby provides a native thread implementation because it is built on top of the JVM. But really, using any of the above variations would have been fine.</p>
    <p>Unfortunately, though, it’s not all clear sailing with JRuby. Quite a few gems still use C extensions (i.e. code written in C that Ruby can import). At the moment, you can enable a flag in JRuby that allows it to use C extensions, but doing so is merely a temporary solution because this option is expected to be removed from JRuby in future releases.</p>
    <p>This could be an issue, for example, if you’re using <a href="http://pryrepl.org/" rel="nofollow external" class="bo">Pry</a> (a replacement for Ruby’s <code>irb</code> REPL). Pry works fine with JRuby, but you wouldn’t be able to take advantage of the equally amazing <a href="https://rubygems.org/gems/pry-plus" rel="nofollow external" class="bo">pry-plus</a> extension, which offers many extra debugging capabilities, because some of its dependencies rely on C extensions.</p>
    <p>I’ve worked around this limitation somewhat by using <a href="https://github.com/nixme/pry-nav" rel="nofollow external" class="bo">pry-nav</a>. It’s not as good and can be a little buggy in places when used under JRuby, but it gets the job done.</p>
    <h3>Bundler</h3>
    <p>To help us create the gem, we’ll use the popular <a href="http://bundler.io/" rel="nofollow external" class="bo">Bundler</a> gem.</p>
    <p>Bundler is primarily designed to help you manage a project’s dependencies. If you’ve not used it before, then don’t worry because we’ll be taking advantage of a lesser known feature anyway, which is its ability to generate a gem boilerplate. (It also provides some other tools that will help us manage our gem’s packaging, which I’ll get into in more detail later on.)</p>
    <p>Let’s begin by installing Bundler:</p>
    <pre><code>&#x000A;    gem install bundler&#x000A;    </code></pre>
    <p>Once Bundler is installed, we can use it to create our gem. But before doing that, let’s review some other dependencies that we’ll need.</p>
    <h3>Dependencies</h3>
    <p>Developing the Sinderella gem requires five dependencies. Four are needed during the development process and won’t be needed in production. The fifth is a “hard” dependency, meaning that it is needed for the Sinderella gem to function properly.</p>
    <ul>
    <li><a href="http://rubygems.org/" rel="nofollow external" class="bo">RubyGems</a></li>
    <li><a href="http://rspec.info/" rel="nofollow external" class="bo">RSpec</a></li>
    <li><a href="http://guardgem.org/" rel="nofollow external" class="bo">Guard</a></li>
    <li><a href="http://pryrepl.org/" rel="nofollow external" class="bo">Pry</a></li>
    <li><a href="https://rubygems.org/gems/crimp" rel="nofollow external" class="bo">Crimp</a></li>
    </ul>
    <p>Of these dependencies, Crimp and RSpec are specific to Sinderella. So, when developing your own gem, you would likely replace them with other gems.</p>
    <h4>RubyGems</h4>
    <p>We need to <a href="https://rubygems.org/pages/download" rel="nofollow external" class="bo">install RubyGems</a> in order to take advantage of the package manager and its built-in <code>gem</code> commands (which Bundler will wrap with its own enhancements).</p>
    <h4>RSpec</h4>
    <p>RSpec is a testing framework for the Ruby programming language. We’ll cover this in more detail later on in the article.</p>
    <p>When building your own gem, you might want to swap RSpec for a different testing tool. Another popular option is <a href="http://cukes.info/" rel="nofollow external" class="bo">Cucumber</a>.</p>
    <h4>Guard</h4>
    <p>Guard is a command-line tool that responds to events. We’ll be using it to more easily write code for test-driven development. It works by monitoring files that you tell it to watch and then, when it notices changes to those files, triggering some command that you specify based on the type of file that was changed.</p>
    <p>This comes in really handy when you’re running tests in a multiplexer such as <a href="http://tmux.sourceforge.net/" rel="nofollow external" class="bo">tmux</a> or when using a terminal such as <a href="http://www.iterm2.com/" rel="nofollow external" class="bo">iTerm2</a> (which supports multiple terminal windows being open at once), because while you’re editing the code in one terminal, you can get instant feedback to breaking tests as you work on the code. This is known as a tight feedback loop (more on this later).</p>
    <h4>Pry</h4>
    <p>Pry is a replacement REPL for Ruby’s standard <code>irb</code>. It offers everything the standard <code>irb</code> does but with a lot of additional features. It’s useful for testing code to see how it works and whether the Ruby interpreter fails to run it. It’s also useful for debugging code when something doesn’t work the way you expect.</p>
    <p>It didn’t have much of a presence in the development of Sinderella, but it is such an important tool that I felt it deserved more than a cursory mention. For example, if you’re unsure of how a particular Ruby feature works, you could test drive it in Pry.</p>
    <p>If you want to learn more about how to use it, then watch the <a href="http://pryrepl.org/" rel="nofollow external" class="bo">screencast on Pry’s home page</a>.</p>
    <h4>Crimp</h4>
    <p>Crimp is a gem released by the BBC that allows you to convert a piece of data into a MD5 hash.</p>
    <h3>Generating A Boilerplate</h3>
    <p>OK, now we’ve finally gotten to the point where we can generate the set-up files that will configure our gem file.</p>
    <p>As mentioned, Bundler has the tools to generate the foundation of a gem so that we don’t have to type it all out by hand.</p>
    <p>Now, open up the terminal and run the following command:</p>
    <pre><code>&#x000A;    bundle gem sinderella&#x000A;    </code></pre>
    <p>When that command is run, the following is generated:</p>
    <pre><code>&#x000A;    ❯ bundle gem sinderella&#x000A;      create  sinderella/Gemfile&#x000A;      create  sinderella/Rakefile&#x000A;      create  sinderella/LICENSE.txt&#x000A;      create  sinderella/README.md&#x000A;      create  sinderella/.gitignore&#x000A;      create  sinderella/sinderella.gemspec&#x000A;      create  sinderella/lib/sinderella.rb&#x000A;      create  sinderella/lib/sinderella/version.rb&#x000A;    Initializing git repo in /path/to/Sinderella&#x000A;    </code></pre>
    <p>Let’s take a moment to review what we have.</p>
    <h4>Folder Structure</h4>
    <p>Bundler has automatically created a <code>lib</code> directory for us, which holds a single Ruby file named after our project. The name of the directory is extracted from the name provided via the <code>bundle gem</code> command.</p>
    <p>Be aware that if you specify a hyphen (<code>-</code>) in the gem’s name, then Bundler will create a deeper folder structure by using the hyphen as a delimiter. For example, if your command looks like <code>bundle gem foo-bar</code>, then the following directory structure would be created:</p>
    <pre><code>&#x000A;    ├── lib&#x000A;    │   └── foo&#x000A;    │       ├── bar&#x000A;    │       │   ├── bar.rb&#x000A;    │       │   └── version.rb&#x000A;    │       └── bar.rb&#x000A;    </code></pre>
    <p>This is actually quite useful when you’re producing multiple gems that are all namespaced under a single project. For a real-world example of this, look at <a href="https://github.com/BBC-News/" title="alephant" rel="nofollow external" class="bo">BBC News’ GitHub repository</a>, which has multiple open-source gems published under the namespace <code>alephant</code>.</p>
    <h4>gemspec</h4>
    <p>The <code>gemspec</code> file is used to define the particular configuration of your gem. If you weren’t using Bundler, then you would need to manually create this file (according to RubyGems’ documentation).</p>
    <p>Below is what Bundler generates for us:</p>
    <pre><code>&#x000A;    # coding: utf-8&#x000A;    lib = File.expand_path('../lib', __FILE__)&#x000A;    $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)&#x000A;    require 'sinderella/version'&#x000A;    &#x000A;    Gem::Specification.new do |spec|&#x000A;      spec.name          = "sinderella"&#x000A;      spec.version       = Sinderella::VERSION&#x000A;      spec.authors       = ["Integralist"]&#x000A;      spec.email         = ["<a href="mailto:mark.mcdx@gmail.com">mark.mcdx@gmail.com</a>"]&#x000A;      spec.summary       = %q{TODO: Write a short summary. Required.}&#x000A;      spec.description   = %q{TODO: Write a longer description. Optional.}&#x000A;      spec.homepage      = ""&#x000A;      spec.license       = "MIT"&#x000A;    &#x000A;      spec.files         = `git ls-files -z`.split("\x0")&#x000A;      spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }&#x000A;      spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})&#x000A;      spec.require_paths = ["lib"]&#x000A;    &#x000A;      spec.add_development_dependency "bundler", "~&gt; 1.5"&#x000A;      spec.add_development_dependency "rake"&#x000A;    end&#x000A;    </code></pre>
    <p>As you’ll see later, this is a basic outline of the final gemspec file that we’ll need to create. We’ll end up adding to this file some of the other dependencies that our gem will need to run (both development and production dependencies).</p>
    <p>For now, note the following details:</p>
    <ul>
    <li>
    <code>$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)</code><br>
    This adds the <code>lib</code> directory to Ruby’s load path, which makes <code>require</code>’ing files elsewhere in the code a little cleaner.</li>
    <li>
    <code>require 'sinderella/version'</code><br>
    This loads in a <code>version.rb</code> file, which was generated when Bundler constructed our boilerplate. This file serves as a way to implement <a href="http://semver.org/" rel="nofollow external" class="bo">semantic versioning</a> in our gem releases. Every time we release the gem, we’ll need to update the version number; then, when we run the particular Bundler command to release the gem, it will automatically pull in the updated value to our <code>gemspec</code> file.</li>
    <li>
    <code>Gem::Specification.new do |spec|</code><br>
    Here, we define a new specification and include properties such as the name of the gem, the version number (see the previous point), a list of the authors of the gem and a contact email address. We can also include some descriptive text about the gem.</li>
    <li>Next, we define the files to include in the gem. Any executable files found are injected dynamically into the file by looping through a <code>bin</code> directory (if one is found). We also dynamically inject a list of test files (which we’ll see later on when we create a <code>spec</code> folder to hold the tests that will ensure that the gem works as expected).</li>
    <li>Finally, we define the dependencies, including both runtime and development dependencies. At the moment, there is only the latter, but soon enough we’ll have one runtime dependency to add.</li>
    </ul>
    <p>The RubyGems guides has <a href="http://guides.rubygems.org/specification-reference/" rel="nofollow external" class="bo">full details on the specification</a>. You could configure a whole host of settings, but Bundler helps us by defining the essential ones.</p>
    <h4>Gemfile</h4>
    <p>In a typical Ruby project, you’ll find that the <code>Gemfile</code> is filled with a list of dependencies, which Bundler then collates and installs for you. In this instance, because we’re generating a gem and not writing a standard application, our <code>Gemfile</code> will actually be pretty bare, made up of two lines: one to tell Bundler where to source the gems from, and the other to inform Bundler that the dependencies are listed in the <code>gemspec</code> file instead.</p>
    <h4>Rakefile</h4>
    <p>Again, in a typical Ruby application, a <code>Rakefile</code> will contain many different tasks (written in Ruby) that you can execute via the command line. In this case, a one-line <code>Rakefile</code> has been provided that loads <code>bundler/gem_tasks</code>. That in turn loads additional <code>rake</code> commands that Bundler adds to make it easier to build and deploy your gem. We’ll see how to use these commands later.</p>
    <h4>LICENSE.txt</h4>
    <p>Because we’re releasing code that could potentially be used by other developers, Bundler generates an MIT licence by default and dynamically injects the current year and your user name into it.</p>
    <p>Feel free to either delete it or replace it with another license if the MIT one doesn’t fit your needs, although it’s pretty standard and relevant to most projects.</p>
    <h4>README</h4>
    <p>Lastly, Bundler has taken the tediousness out of generating a <code>README</code> file. It includes <code>TODO</code> messages wherever relevant, so that you know what needs to be manually added before the gem can be built (such as a description of the gem and a code example that shows how you expect the gem to be used). It also automatically generates installation instructions and a section on how other developers can fork your code and contribute new features and bug fixes.</p>
    <p>One other benefit of Bundler is that it delivers a consistent code base across all gems you create. All gems will have the same structure, and the consistency across content such as the README file will make it easier for users who integrate more than one of your gems to understand them.</p>
    <h3>Test-Driven Development</h3>
    <p>Test-driven development (TDD) is the process of building code on top of supporting tests. Sinderella was developed using its principles.</p>
    <p>The guiding steps are “red, green, refactor,” and TDD fundamentally breaks down as the following:</p>
    <ol>
    <li>Write a test.</li>
    <li>Run the test and watch it fail (because there is no code yet for it to pass).</li>
    <li>Write the least amount of code to pass the test (literally, hack it together).</li>
    <li>Refactor the code so that it’s cleaner and better written.</li>
    <li>If the test has failed through refactoring, then start the red, green, refactoring process again.</li>
    </ol>
    <p>This is sometimes referred to as a tight feedback loop: getting quick or instant feedback on whether code is working.</p>
    <p>By writing the tests first, you ensure that every line of code exists for a reason. This is an incredibly powerful principle and one you should recall when caught in a debate over whether TDD “sucks” or “takes too long.”</p>
    <p>Starting a project with tests can feel daunting. But in addition to ensuring that every line of code exists for a reason, it provides an opportunity for you to properly design the APIs.</p>
    <h3>RSpec</h3>
    <p>As for writing tests for Sinderella, I chose to use <a href="http://rspec.info/" rel="nofollow external" class="bo">RSpec</a>, which is described thus on its website:</p>
    <blockquote>
    <p>RSpec is a testing tool for the Ruby programming language. Born under the banner of behaviour-driven development, it is designed to make test-driven development a productive and enjoyable experience</p>
    </blockquote>
    <p>In order to use RSpec in our gem, we’ll need to update the <code>gemspec</code> file to include more dependencies:</p>
    <pre><code>&#x000A;    spec.add_development_dependency "rspec"&#x000A;    spec.add_development_dependency "rspec-nc"&#x000A;    spec.add_development_dependency "guard"&#x000A;    spec.add_development_dependency "guard-rspec"&#x000A;    spec.add_development_dependency "pry"&#x000A;    spec.add_development_dependency "pry-remote"&#x000A;    spec.add_development_dependency "pry-nav"&#x000A;    </code></pre>
    <p>As you can see, we’ve added RSpec to our list of dependencies, but we’ve also included <a href="https://github.com/twe4ked/rspec-nc" rel="nofollow external" class="bo">rspec-nc</a>, which provides native notifications on Mac OS X (rspec-nc is a nicety and not essential to produce the gem). Having notifications at the operating-system level can be quite handy, allowing you to do other things (perhaps check email) while tests run in the background.</p>
    <p>We’ve also added (as you would expect) <code>guard</code> as a dependency, as well as <code>guard-rspec</code>, which Guard will need in order to understand how to handle RSpec-specific requests. This suite of Pry tools will debug any problems we come across and will be useful for any gems you develop in future.</p>
    <h4>RSpec Rake Tasks</h4>
    <p>Now that we’ve updated <code>gemspec</code> to include RSpec as a dependency, we’ll need to add an RSpec-related Rake task to our <code>Rakefile</code>, which will enable us (manually) or Guard to execute the task and run the RSpec test suite:</p>
    <pre><code>&#x000A;    require 'rspec/core/rake_task'&#x000A;    require 'bundler/gem_tasks'&#x000A;    &#x000A;    # Default directory to look in is `/specs`&#x000A;    # Run with `rake spec`&#x000A;    RSpec::Core::RakeTask.new(:spec) do |task|&#x000A;      task.rspec_opts = ['--color', '--format', 'nested']&#x000A;    end&#x000A;    &#x000A;    task :default =&gt; :spec&#x000A;    </code></pre>
    <p>In the updated version of <code>Rakefile</code> above, we are loading an additional file that is packaged with RSpec (<code>require 'rspec/core/rake_task'</code>). This new file adds some RSpec-related modules and classes for us to use.</p>
    <p>Once this code has loaded, we create a new instance of the <code>RakeTask</code> class (created when we loaded <code>rspec/core/rake_task</code>) and pass it a code block to execute. The code block we pass will define the options for our RSpec test suite.</p>
    <h4>Spec Files</h4>
    <p>Now that the majority of the RSpec test suite configuration is in place, the last thing we need to do is add a test file.</p>
    <p>Let’s create a <code>spec</code> directory and, inside that, create <code>sinderella_spec.rb</code>:</p>
    <pre><code>&#x000A;    require 'spec_helper'&#x000A;    &#x000A;    describe Sinderella do&#x000A;      it 'does stuff' do&#x000A;        pending # no code yet&#x000A;      end&#x000A;    end&#x000A;    </code></pre>
    <p>You’ll see that we’ve included a temporary specification that states that the code “does stuff.” When the test suite is run, then this test will not cause any errors, even though no code has been implemented yet, because we have marked the test as “pending” (an RSpec-specific command). At this point, we’re only interested in getting a barebones set-up in place; we’ll flesh out the tests soon enough.</p>
    <p>You may have noticed that we’re also loading another file, named <code>spec_helper.rb</code>. This type of file is typical in an RSpec suite and is used to load any dependencies or libraries that are required for the tests to run. The content of the spec helper file will look like this:</p>
    <pre><code>&#x000A;    require 'pry'&#x000A;    require 'Sinderella'&#x000A;    </code></pre>
    <p>All we’ve done here is load Pry (in case we need it for debugging) and the main Sinderella gem code (because this is what we want to test).</p>
    <h3>Guard And tmux</h3>
    <p>At this point, we’ve gone over the set-up and preparation of RSpec and Rake (to get our testing framework in place). We also know what Guard is and how it helps us to test the code. Now, let’s go ahead and add a <code>Guardfile</code> to the root directory, with the following contents:</p>
    <pre><code>&#x000A;    guard 'rspec' do&#x000A;      # watch /lib/ files&#x000A;      watch(%r{^lib/(.+)\.rb$}) do |m|&#x000A;        "spec/#{m[1]}_spec.rb"&#x000A;      end&#x000A;    &#x000A;      # watch /spec/ files&#x000A;      watch(%r{^spec/(.+)\.rb$}) do |m|&#x000A;        "spec/#{m[1]}.rb"&#x000A;      end&#x000A;    end&#x000A;    </code></pre>
    <p>This file tells Guard that we’re using RSpec to run our tests. It also defines which directories to watch for changes and what to do when it notices changes. In this case, we’re using <a href="http://www.regular-expressions.info/" rel="nofollow external" class="bo">regular expressions</a> to match any files in the <code>lib</code> or <code>spec</code> directory and to execute the relevant RSpec command that runs our tests (or to run one specific test).</p>
    <p>We’ll see in a minute how to actually run Guard. For now, let’s see how tmux fits this workflow.</p>
    <h4>tmux</h4>
    <p>Some developers prefer to have separate applications open (for example, a code editor such as <a href="http://www.sublimetext.com/" rel="nofollow external" class="bo">Sublime Text</a> and a terminal application to run tests). I prefer to use tmux to have multiple terminal shells open on one screen and to have Vim open on another screen to edit code. Thus, I can edit code and get visual feedback from the terminal about the state of the tests all on one screen. You don’t need to follow the exact same approach. As mentioned, there are other ways to get feedback, but I have found tmux and Vim to be the most suitable.</p>
    <p>So, we have two tmux panes open, one in which Vim is running, and the other in which a terminal runs the command <code>bundle exec guard</code> (this is how we actually run Guard).</p>
    <p>That command will return something like the following back to the terminal:</p>
    <pre><code>&#x000A;    ❯ bundle exec guard&#x000A;    09:53:55 - INFO - Guard is using Tmux to send notifications.&#x000A;    09:53:55 - INFO - Guard is using TerminalTitle to send notifications.&#x000A;    09:53:55 - INFO - Guard::RSpec is running&#x000A;    09:53:55 - INFO - Guard is now watching at '/path/to/Sinderella' &#x000A;    &#x000A;    From: /path/to/Sinderella/sinderella.gemspec @ line 1 :&#x000A;    &#x000A;     =&gt; 1: # coding: utf-8&#x000A;        2: lib = File.expand_path('../lib', __FILE__)&#x000A;        3: $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)&#x000A;        4: require 'sinderella/version'&#x000A;        5: &#x000A;        6: Gem::Specification.new do |spec|&#x000A;    </code></pre>
    <p>From this point on, you can press the <code>Return</code> key to run all tests at once, which will display the following message in the terminal:</p>
    <pre><code>&#x000A;    09:57:41 - INFO - Run all&#x000A;    09:57:41 - INFO - Running all specs&#x000A;    </code></pre>
    <p>This will be followed by the number of passed and failed tests and any errors that have occurred.</p>
    <h3>Continuous Integration With Travis CI</h3>
    <p>As mentioned at the beginning, continuous integration (CI) is the process of merging code with a central repository in order to prevent integration problems down the road in a project’s life cycle.</p>
    <p>We’ll use the free Travis CI service (which you should have signed up for by now).</p>
    <p>Upon first viewing your “<a href="https://travis-ci.org/profile" rel="nofollow external" class="bo">Accounts</a>” page in Travis CI, you’ll be presented with a complete list of all of your public GitHub repositories, from which you can select ones for Travis CI to monitor. Then, any time you push a commit to GitHub, Travis CI will run your tests.</p>
    <p>Once you have selected repositories, you’ll be redirected to a GitHub “hooks” page, where you can confirm and authorize the configuration.</p>
    <p>The <a href="https://travis-ci.org/Integralist/Sinderella" rel="nofollow external" class="bo">Travis CI page for the Sinderella gem</a> is where you can view the entire build history, including both passed and failed tests.</p>
    <h4>.travis.yml</h4>
    <p>To complete the configuration, we need to add a <code>.travis.yml</code> file. If you’ve enabled your repository from your Travis CI account and you don’t have a <code>.travis.yml</code> file, then Travis CI will throw an error and complain that you need one. Let’s look at the one we’ve set up for Sinderella:</p>
    <pre><code>&#x000A;    language: ruby&#x000A;    cache: bundler&#x000A;    &#x000A;    rvm:&#x000A;      - jruby&#x000A;      - 2.0.0&#x000A;    &#x000A;    script: 'bundle exec rake'&#x000A;    &#x000A;    notifications:&#x000A;      email:&#x000A;        recipients:&#x000A;          - <a href="mailto:my@email.com">my@email.com</a>&#x000A;        on_failure: change&#x000A;        on_success: never&#x000A;    </code></pre>
    <p>Let’s go through each property to understand what it does:</p>
    <ul>
    <li>
    <code>language: ruby</code><br>
    Here, we’re telling Travis CI that the language in which we’re writing tests is Ruby.</li>
    <li>
    <code>cache: bundler</code><br>
    This tells Travis CI that we want it to cache the gems we’ve specified. (Running Bundler can be a slow process, and if your gems are unlikely to change often, then you don’t want to keep running <code>bundle install</code> every time you push a commit, because we want our tests to run as quickly as possible.)</li>
    <li>
    <code>rvm:</code><br>
    This specifies the different Ruby versions and engines that we want our tests to run against (in this case, JRuby and MRI 2.0.0).</li>
    <li>
    <code>script: 'bundle exec rake'</code><br>
    This gives Travis CI the command it requires to run the tests.</li>
    <li>
    <code>notifications:</code><br>
    This indicates how we want Travis CI to notify us. Here, we’re specifying an email address to receive the notifications. We’re also specifying that an email should be sent only if a failure has occurred (there’s no point in getting thousands of emails telling us that nothing is wrong).</li>
    </ul>
    <h4>Preventing a Test Run</h4>
    <p>If you’re committing a change that doesn’t affect your code or tests, then you don’t want to waste time watching those non-breaking changes trigger a test run on Travis CI (no matter how fasts the tests are).</p>
    <p>The easiest way to avoid this is to add <code>[ci skip]</code> anywhere in your commit message. Travis CI will see this and then happily ignore the commit.</p>
    <h3>Code Coverage And Statistics With Coveralls.io</h3>
    <p>One last service we’ll use is <a href="https://coveralls.io" rel="nofollow external" class="bo">Coveralls</a>, which you should have already registered for.</p>
    <blockquote>
    <p>Coveralls works with your continuous integration server to give you test coverage history and statistics. Free for open source, pro accounts for private repos.</p>
    </blockquote>
    <p>When you log into Coveralls for the first time, it will ask you to select repositories to monitor. It works like Travis CI, listing all of your repositories for you to enable and disable access. (You can also click a button to resynchronize the repository list, in case you’ve added a repository since last syncing).</p>
    <p>To set up Coveralls, we need to add a file that tells Coverall what to do. For our project, we need to add a file to the root directory named <code>.coveralls.yml</code>, in which we’ll include a single line of configuration:</p>
    <pre><code>&#x000A;    service_name: travis-ci&#x000A;    </code></pre>
    <p>This tells Coveralls that we’re using Travis CI as our CI server. (If you’ve signed up for a Pro account, then use <code>travis-pro</code> instead.)</p>
    <p>We also need to add the Coveralls gem to our <code>gemspec</code>:</p>
    <pre><code>&#x000A;    spec.add_development_dependency "coveralls"&#x000A;    </code></pre>
    <p>Finally, we need to include Coveralls’ code in our <code>spec_helper.rb</code> file:</p>
    <pre><code>&#x000A;    require 'coveralls'&#x000A;    Coveralls.wear!&#x000A;    &#x000A;    require 'pry'&#x000A;    require 'sinderella'&#x000A;    </code></pre>
    <p>Notice that we have to load the code before the Sinderella code. If you load Coveralls after the application’s code has loaded, then it wouldn’t be able to hook into the application properly.</p>
    <p>Let’s return to our TDD process.</p>
    <h3>Skeleton Specification</h3>
    <p>When following TDD, I prefer to create a skeleton of a test suite, so that I have some idea of the type of API to develop. Let’s change the contents of the <code>sinderella_spec.rb</code> file to have a few empty tests:</p>
    <pre><code>&#x000A;    require 'spec_helper'&#x000A;    &#x000A;    describe Sinderella do&#x000A;      let(:data) {{ :key =&gt; 'value' }}&#x000A;      let(:till_midnight) { 0 }&#x000A;    &#x000A;      describe '.transforms(data, till_midnight)' do&#x000A;        it 'returns a hash of the passed data' do&#x000A;          pending&#x000A;        end&#x000A;    &#x000A;        it 'stores original and transformed data' do&#x000A;          pending&#x000A;        end&#x000A;    &#x000A;        it 'restores the data to its original state after set time' do&#x000A;          pending&#x000A;        end&#x000A;      end&#x000A;    &#x000A;      describe '.get(id)' do&#x000A;        context 'before midnight (before time expired)' do&#x000A;          it 'returns transformed data' do&#x000A;            pending&#x000A;          end&#x000A;        end&#x000A;    &#x000A;        context 'past midnight (after time expired)' do&#x000A;          it 'returns original data' do&#x000A;            pending&#x000A;          end&#x000A;        end&#x000A;      end&#x000A;    &#x000A;      describe '.midnight(id)' do&#x000A;        it 'restores the data to its original state' do&#x000A;          pending&#x000A;        end&#x000A;      end&#x000A;    end&#x000A;    </code></pre>
    <p>Notice the <code>pending</code> command, which is provided by RSpec and allows the tests to run without throwing an error. (The suite will highlight pending tests that still need to be implemented so that you don’t forget about them.)</p>
    <p>You could also use the <code>fail</code> command, but <code>pending</code> is recommended for unimplemented tests, particularly before you’ve written the code to execute them. <a href="https://www.relishapp.com/rspec/rspec-core/v/2-3/docs/pending/pending-examples" rel="nofollow external" class="bo">Relish demonstrates some examples.</a></p>
    <p>From here on, I follow the full TDD process and write the code from the outside in: red, green, refactor.</p>
    <p>For the first test I wrote for Sinderella, I realized that my code needs a way to create an MD5 hash from a data object, and that’s when I reached for the BBC News’ gem, <a href="https://rubygems.org/gems/crimp" title="ime_d" rel="nofollow external" class="bo">Crimp</a>. Thus, I had to update the <code>gemspec</code> file to include a new runtime dependency: <code>spec.add_runtime_dependency "crimp"</code>.</p>
    <p>I won’t go step by step into how I TDD’ed the code because it isn’t relevant to this article. We’re focusing more on the principles of creating a gem, not on details of implementation. But you can get all of the gruesome details from the public list of commits in <a href="https://github.com/Integralist/Sinderella/commits/master" rel="nofollow external" class="bo">Sinderella’s GitHub repository</a>.</p>
    <p>Also, you might not even be interested in the RSpec testing framework and might be planning on using a different framework to write your gem. That’s fine. Anyway, what follows is the full Sinderella specification file (as of February 2014):</p>
    <h4>sinderella_spec.rb</h4>
    <pre><code>&#x000A;    require 'spec_helper'&#x000A;    &#x000A;    describe Sinderella do&#x000A;      let(:data) {{ :key =&gt; 'value' }}&#x000A;      let(:till_midnight) { 0 }&#x000A;    &#x000A;      def create_new_instance&#x000A;        @id = subject.transforms(data, till_midnight) do |data|&#x000A;          data.each do |key, value|&#x000A;            data.tap { |d| d[key].upcase! }&#x000A;          end&#x000A;        end&#x000A;      end&#x000A;    &#x000A;      describe '.transforms(data, till_midnight)' do&#x000A;        it 'returns a MD5 hash of the provided data' do&#x000A;          create_new_instance&#x000A;          expect(@id).to be_a String&#x000A;          expect(@id).to eq '24e73d3a4f027ff81ed4f32c8a9b8713'&#x000A;        end&#x000A;      end&#x000A;    &#x000A;      describe '.get(id)' do&#x000A;        context 'before midnight (before time expired)' do&#x000A;          it 'returns the transformed data' do&#x000A;            Sinderella.stub(:check)&#x000A;            create_new_instance&#x000A;            expect(subject.get(@id)).to eq({ :key =&gt; 'VALUE' })&#x000A;          end&#x000A;        end&#x000A;    &#x000A;        context 'past midnight (after time expired)' do&#x000A;          it 'returns the original data' do&#x000A;            create_new_instance&#x000A;            Sinderella.reset_data_at @id&#x000A;            expect(subject.get(@id)).to eq({ :key =&gt; 'value' })&#x000A;          end&#x000A;        end&#x000A;      end&#x000A;    &#x000A;      describe '.midnight(id)' do&#x000A;        context 'before midnight (before time expired)' do&#x000A;          it 'restores the data to its original state' do&#x000A;            Sinderella.stub(:check)&#x000A;            create_new_instance&#x000A;            subject.midnight(@id)&#x000A;            expect(subject.get(@id)).to eq({ :key =&gt; 'value' })&#x000A;          end&#x000A;        end&#x000A;      end&#x000A;    end&#x000A;    </code></pre>
    <h4>data_store_spec.rb</h4>
    <pre><code>&#x000A;    require 'spec_helper'&#x000A;    &#x000A;    describe DataStore do&#x000A;      let(:instance)    { DataStore.instance }&#x000A;      let(:original)    { 'bar' }&#x000A;      let(:transformed) { 'BAR' }&#x000A;    &#x000A;      before(:each) do&#x000A;        instance.set({&#x000A;          :id =&gt; 'foo',&#x000A;          :original =&gt; original,&#x000A;          :transformed =&gt; transformed&#x000A;        })&#x000A;      end&#x000A;    &#x000A;      describe 'set(data)' do&#x000A;        it 'stores original and transformed data' do&#x000A;          expect(instance.get('foo')[:original]).to eq(original)&#x000A;          expect(instance.get('foo')[:transformed]).to eq(transformed)&#x000A;        end&#x000A;      end&#x000A;    &#x000A;      describe 'get(id)' do&#x000A;        it 'returns data object' do&#x000A;          expect(instance.get('foo')).to be_a Hash&#x000A;          expect(instance.get('foo').key?(:original)).to be true&#x000A;          expect(instance.get('foo').key?(:transformed)).to be true&#x000A;        end&#x000A;      end&#x000A;    &#x000A;      describe 'reset(id)' do&#x000A;        it 'replaces the transformed data with original data' do&#x000A;          instance.reset('foo')&#x000A;          foo = instance.get('foo')&#x000A;          expect(foo[:original]).to eq(foo[:transformed])&#x000A;        end&#x000A;      end&#x000A;    end&#x000A;    </code></pre>
    <h4>Passing Specification</h4>
    <p>Here is the output of our passed test suite:</p>
    <pre><code>&#x000A;    ❯ rake spec&#x000A;    /path/to/.rubies/jruby-1.7.9/bin/jruby -S rspec ./spec/data_store_spec.rb ./spec/sinderella_spec.rb --color --format nested&#x000A;    &#x000A;    DataStore&#x000A;      set(data)&#x000A;        stores original and transformed data&#x000A;      get(id)&#x000A;        returns data object&#x000A;      reset(id)&#x000A;        replaces the transformed data with original data&#x000A;    &#x000A;    Sinderella&#x000A;      .transforms(data, till_midnight)&#x000A;        returns a MD5 hash of the provided data&#x000A;      .get(id)&#x000A;        before midnight (before time expired)&#x000A;          returns the transformed data&#x000A;        past midnight (after time expired)&#x000A;          returns the original data&#x000A;      .midnight(id)&#x000A;        before midnight (before time expired)&#x000A;          restores the data to its original state&#x000A;    &#x000A;    Finished in 0.053 seconds&#x000A;    7 examples, 0 failures&#x000A;    </code></pre>
    <h3>Design Patterns</h3>
    <p><a href="http://en.wikipedia.org/wiki/Design_pattern" rel="nofollow external" class="bo">According to Wikipedia</a>:</p>
    <blockquote>
    <p>A design pattern in architecture and computer science is a formal way of documenting a solution to a design problem in a particular field of expertise.</p>
    </blockquote>
    <p>Many design patterns exist, one of which in particular is usually <a href="https://www.google.com/search?q=singleton%20design%20pattern%20is%20bad#q=singleton%20design%20pattern%20good%20or%20bad" rel="nofollow external" class="bo">frowned on</a>, the <a href="http://en.wikipedia.org/wiki/Singleton_pattern" rel="nofollow external" class="bo">Singleton</a> pattern.</p>
    <p>I won’t debate the merits or problems of the Singleton design pattern, but I opted to use it in Sinderella to implement the <code>DataStore</code> class (which is the object that stores the original and transformed data), because what would be the point of having multiple instances of <code>DataStore</code> if the data is expected to be shared from a single access point?</p>
    <p>Luckily, Ruby makes it really easy to create a Singleton. Just add <code>include Singleton</code> in your class definition.</p>
    <p>Once you’ve done that, you will be able to access a single instance of your class only via an <code>instance</code> property — for example, <code>MyClass.instance.some_method()</code>.</p>
    <p>We saw the specification (or test file) for <code>DataStore</code> in the previous section. Below is the full implementation of <code>DataStore</code>:</p>
    <pre><code>&#x000A;    require 'singleton'&#x000A;    &#x000A;    class DataStore&#x000A;      include Singleton&#x000A;    &#x000A;      def set(data)&#x000A;        hash_data = {&#x000A;          :original    =&gt; data[:original],&#x000A;          :transformed =&gt; data[:transformed]&#x000A;        }&#x000A;    &#x000A;        container.store(data[:id], hash_data)&#x000A;      end&#x000A;    &#x000A;      def get(id)&#x000A;        container.fetch(id)&#x000A;      end&#x000A;    &#x000A;      def reset(id)&#x000A;        original  = container.fetch(id)[:original]&#x000A;        hash_data = {&#x000A;          :original =&gt; original,&#x000A;          :transformed =&gt; original&#x000A;        }&#x000A;    &#x000A;        container.store(id, hash_data)&#x000A;      end&#x000A;    &#x000A;      private&#x000A;    &#x000A;      def container&#x000A;        @store ||= Hash.new&#x000A;      end&#x000A;    end&#x000A;    </code></pre>
    <h3>Badges</h3>
    <p>You might have seen some nice green badges in your favorite GitHub repository, indicating whether the tests associated with the code passed or not. Adding these to the README is straightforward enough:</p>
    <pre><code>&#x000A;    [![Build Status](<a href="https://travis-ci.org/Integralist/Sinderella.png?branch=master)%5D(https://travis-ci.org/Integralist/Sinderella">https://travis-ci.org/Integralist/Sinderella.png?branch=master)](https://travis-ci.org/Integralist/Sinderella</a>) &#x000A;    &#x000A;    [![Gem Version](<a href="https://badge.fury.io/rb/sinderella.png)%5D(http://badge.fury.io/rb/sinderella">https://badge.fury.io/rb/sinderella.png)](http://badge.fury.io/rb/sinderella</a>)&#x000A;    &#x000A;    [![Coverage Status](<a href="https://coveralls.io/repos/Integralist/Sinderella/badge.png)%5D(https://coveralls.io/r/Integralist/Sinderella">https://coveralls.io/repos/Integralist/Sinderella/badge.png)](https://coveralls.io/r/Integralist/Sinderella</a>)&#x000A;    </code></pre>
    <p>The first badge is provided by Travis CI, which you can read more about <a href="http://docs.travis-ci.com/user/status-images/" rel="nofollow external" class="bo">in the documentation</a>.</p>
    <p>The second is provided by RubyGems. You’ll notice on your gem’s page a “badge” link, which provides the required code and format (in this case, in <a href="http://en.wikipedia.org/wiki/Markdown" rel="nofollow external" class="bo">Markdown</a> format).</p>
    <p>The third is provided by Coveralls. When you visit your repository page in the Coveralls application, you’ll see a link to “Get badge URLS”; from there, you can select the relevant format.</p>
    <h3>REPL-Driven Development</h3>
    <p>Tests and TDD are a critical part of the development process but won’t eliminate all bugs by themselves. This is where a tool such as Pry can help you to figure out how a piece of code works and the path that the code takes during a conditioned execution.</p>
    <p>To use Pry, enter the <code>pry</code> command in the terminal. As long as Pry is installed and available from that directory, you’ll be dropped into a Pry session. To view all available commands, run the <code>help</code> command.</p>
    <h4>Testing a Local Gem Build</h4>
    <p>If you want to run the gem outside of the test suite, then you’ll want to use Pry. To do this, we’ll need to build the gem locally and then install that local build.</p>
    <p>To build the gem, run the following command from your gem’s root directory: <code>gem build sinderella.gemspec</code>. This will generate a physical <code>.gem</code> file.</p>
    <p>Once the gem is built and a <code>.gem</code> file has been created, you can install it from the local file with the following command: <code>gem install ./sinderella-0.0.1.gem</code>.</p>
    <p>Notice that the built <code>gem</code> file includes the version number, so that you know you’re installing the right one (in case you’ve built multiple versions of the gem).</p>
    <p>After installing the local version of the gem, you can open a Pry session and load the gem with <code>require 'sinderella'</code> and continue to execute your own Ruby code within Pry to test the gem as needed.</p>
    <h3>Releasing Your Gem</h3>
    <p>Once our gem has passed all of our tests and we’ve built and run it locally, we can look to release the gem to the Ruby community by pushing it to the RubyGems server.</p>
    <p>To release our gem, we’ll use the Rake commands provided by Bundler. To view what commands are available, run <code>rake --task</code>. You’ll see something similar to the following output:</p>
    <pre><code>&#x000A;    rake build    # Build sinderella-0.0.1.gem into the pkg directory&#x000A;    rake install  # Build and install sinderella-0.0.1.gem into system gems&#x000A;    rake release  # Create tag v0.0.1 and build and push sinderella-0.0.1.gem t...&#x000A;    rake spec     # Run RSpec code examples&#x000A;    </code></pre>
    <ul>
    <li>
    <code>rake build</code><br>
    This first task does something similar to <code>gem build sinderella.gemspec</code> but placing the gem in a <code>pkg</code> (package) directory.</li>
    <li>
    <code>rake install</code><br>
    The second task does the same as <code>gem install ./sinderella-0.0.1.gem</code> but saves us the extra typing.</li>
    <li>
    <code>rake release</code><br>
    The third task is what we’re most interested at this point. It creates a tag in git, indicating the relevant version number, pulled from the <code>version.rb</code> file that Bundler created for us. It then builds the gem and pushes it to RubyGems.</li>
    <li>
    <code>rake spec</code><br>
    The fourth task runs the tests using the test runner (in this case, RSpec), as defined and configured in the main <code>Rakefile</code>.</li>
    </ul>
    <p>To release our gem, we’ll first need to make sure that the version number in the <code>version.rb</code> file is correct. If it is, then we’ll commit those changes and run the <code>rake release</code> task, which should give the following output:</p>
    <pre><code>&#x000A;    ❯ rake release&#x000A;    sinderella 0.0.1 built to pkg/sinderella-0.0.1.gem.&#x000A;    Tagged v0.0.1.&#x000A;    Pushed git commits and tags.&#x000A;    Pushed sinderella 0.0.1 to rubygems.org.&#x000A;    </code></pre>
    <p>Now we can view the details of the gem at <a href="https://rubygems.org/gems/sinderella" rel="nofollow external" class="bo">https://rubygems.org/gems/sinderella</a>, and other users may access our gem in their own code simply by including <code>require 'sinderella'</code>.</p>
    <h3>Conclusion</h3>
    <p>Thanks to the use of Bundler, the process of creating a gem boilerplate is made a lot simpler. And thanks to the principles of TDD and REPL-driven development, we know that we have a well-tested piece of code that can be reliably shared with the Ruby community.</p>
    <p><em>(al, il)</em></p>
    <hr>
    <p><small>© Mark McDonnell for <a href="http://www.smashingmagazine.com" rel="nofollow external" class="bo">Smashing Magazine</a>, 2014.</small></p>
    </div>
]]>
</Body>
<Summary>        Ruby is a great language. It was designed to foster happiness and productivity in developers, all the while providing tools that are effective and yet focused on simplicity. One of the...</Summary>
<Website>http://www.smashingmagazine.com/2014/04/08/how-to-build-a-ruby-gem-with-bundler-test-driven-development-travis-ci-and-coveralls-oh-my/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/43327/guest@my.umbc.edu/b3ad5de31b195773dc47012b6ad606da/api/pixel</TrackingUrl>
<Tag>coding</Tag>
<Tag>css</Tag>
<Tag>design</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 08 Apr 2014 05:39:39 -0400</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="43325" important="false" status="posted" url="https://my3.my.umbc.edu/posts/43325">
<Title>MySQL Questions and Answers</Title>
<Body>
<![CDATA[
    <div class="html-content">This page contains several questions and a pointer to the answers from w3resource.com MySQL Tutorial.</div>
]]>
</Body>
<Summary>This page contains several questions and a pointer to the answers from w3resource.com MySQL Tutorial.</Summary>
<Website>http://feedproxy.google.com/~r/w3resource/~3/EUzgQUz8mI4/mysql-question-answer.php</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/43325/guest@my.umbc.edu/c2746632ba4a71601f265f4fc0f750ca/api/pixel</TrackingUrl>
<Tag>backend</Tag>
<Tag>css</Tag>
<Tag>frontend</Tag>
<Tag>html</Tag>
<Tag>html5</Tag>
<Tag>javascript</Tag>
<Tag>nosql</Tag>
<Tag>sql</Tag>
<Tag>xhtml</Tag>
<Tag>xml</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 08 Apr 2014 04:30:52 -0400</PostedAt>
<EditAt>Thu, 15 May 2014 09:16:23 -0400</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="43326" important="false" status="posted" url="https://my3.my.umbc.edu/posts/43326">
<Title>How to beat the &#8220;paradox of choice&#8221; in UI design</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p><img alt="thumbnail" src="http://netdna.webdesignerdepot.com/uploads/2014/04/thumbnail2.jpg" width="200" height="160" style="max-width: 100%; height: auto;">“Less is more” is one of the most important minimalistic design principles every designer learns: you read about it a lot, you know it’s really important, but still you might get it all wrong. The important thing is to come around, learn from it, and evolve. And so we did.</p> <p>With the release of Todoist Next in January of this year, we introduced a new design alongside new features. From the beginning, our focus was to modernize the app and improve the user experience across the board. Postponing tasks was one of the things we especially wanted to improve. But it wasn’t as easy as we expected…</p> <h1>Out with the old</h1> <p>The previous version of our app had only two options when it came to rescheduling tasks. Either you chose “Do it today” or “Postpone” (that could be either tomorrow or next occurrence for recurring tasks). Whenever you needed a bit more control you needed to use the full calendar, or type in a new date. On the Web and desktop clients, it’s really easy to type in a new date and time, since you have the physical keyboard and mouse. But on mobile, the experience was a bit broken. You could type in a new date but wasn’t very convenient, especially when you’re in the “one eyeball and one thumb” mode.</p> <p> </p> <h1>In with the new</h1> <p>Since the old system was so limited, we really wanted to give our users more options and make it much more visual so that it would be more flexible and easier to use on mobile devices, but also great on other platforms. At that precise moment, the choice was more.</p> <p>Since we wanted to make a great mobile experience, we used the “mobile first” approach in the development: if it works on mobile, it’s easier to make it work on desktop where you have more screen space and more precise input methods.</p> <p>With all this in mind, we started to explore how it could work and which direction would most help our users. We researched other solutions that were trying to address similar issues to our own, but we felt that most of them were limited and that we could improve upon them, although some of them are really good solutions.</p> <p>A “smart” scheduler was our big idea. A smart system that would look into your tasks and would suggest the best dates magically. For example, when you reschedule a task for next week, the system would look into your current tasks and select a day in the next week with no due tasks. And it would be <em>awesome!</em> For the user it would be a no brainer, with a really nice interface powered by a strong algorithm to fetch the best dates. For the team, it would be a great accomplishment that blended an awesome interface with solid coding into a solid product.</p> <p><a href="http://netdna.webdesignerdepot.com/uploads/2014/04/wdd-internal1.jpg" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/04/wdd-internal1.jpg" width="650" alt="How to beat the “paradox of choice” in UI design" style="max-width: 100%; height: auto;"></a></p> <p><em>Early stages of development: from circular menus to really complex sets of options with date suggestions marked on the calendar and additional feedback on tap.</em></p> <p>Everything was falling into place with the initial developments, and the first mockups were looking promising. We even started to come up with new ideas about how to make it even more powerful. We added an initial group of choices (today, tomorrow, next week, someday), a classic calendar view option, and “date suggestions” that would bring all the magic to the screen. We tried different layouts, even a circular menu, and iterated quickly on the options range (between 6 to 9 options on the screen at a time).</p> <p>Soon we started to think about how to cut interaction steps, how to increase choice options and reduce taps. One of the options would display the classic calendar but that seemed like an unnecessary extra tap, because we could fit everything into the same screen. And so we tested. And tested.</p> <p> </p> <h1>The uh-oh moment</h1> <p>One of the first problems we detected with the “magic” was the lack of feedback on the dates. If the user chose next week, the system added the date but the user had no say in it. Even if it was a free day, you might have wanted the task scheduled for another day. We needed a extra step to show the date that the user could then confirm.</p> <p>Another problem became obvious: we didn’t have enough information about the users to truly make the best possible suggestions. To do so would probably have required a lot of input from the user or, really, spying on everything they do. On top of it all, the coding of such a system was getting really complicated.</p> <p>Also, the interface was getting really cluttered with a lot of choices, and too many taps were required for some simple selections. At this point we had reached a “paradox of choice”—a term coined by <a href="http://www.ted.com/talks/barry_schwartz_on_the_paradox_of_choice" rel="nofollow external" class="bo">Barry Schwartz</a>—we had so many options that actually selecting one was a daunting task in itself.</p> <blockquote> <p>The first solution we started with was an algorithmic solution that would do calculations for you. The idea is smart on paper, but a nightmare to implement since we don’t have enough information to make it really smart. — Todoist founder, Amir Salihefendic.</p> </blockquote> <p>With the precious help of Khoi Vinh (amazing designer and UX guru), we started to realize that we weren’t achieving our goal of simplification, we were making the app <em>more</em> complicated.</p> <p> </p> <h1>Finally overcoming the Paradox of Choice</h1> <p>When developing an app, most of the time your imagination is the limit. This means that it’s easy to go completely overboard. We overselves fell into this trap. From there, we needed to take a step back and rethink the entire system.</p> <p>We strongly advocate simplicity in user interfaces, so our new visual scheduler couldn’t be complicated. Here, we started by using one of of <a href="http://www.ted.com/talks/sheena_iyengar_choosing_what_to_choose" rel="nofollow external" class="bo">Sheena Iyengar’s</a> principles from “The art of choosing”: cut. The option set was restrained and date suggestions were removed altogether.</p> <p><a href="http://netdna.webdesignerdepot.com/uploads/2014/04/wdd-internal2.jpg" rel="nofollow external" class="bo"><img src="http://netdna.webdesignerdepot.com/uploads/2014/04/wdd-internal2.jpg" width="650" alt="How to beat the “paradox of choice” in UI design" style="max-width: 100%; height: auto;"></a></p> <p><em>Although Android and iOS versions work the same way, the UI was adjusted to better fit each platform. Although it’s the final layout, the options set would still be adjusted before the release.</em></p> <p>The layout was also simplified. The final solution is a 3×2 grid of options, with access to a full calendar as one of the options, so it’s easy to know what to expect at any point. Some of the other solutions might have been good choices, but after testing, we figured they were harder to use and required a steeper learning curve. Sometimes it’s just better to keep it simple.</p> <p>There was a lot of effort put into developing the system and, in the end, we decided on an easily understandable group of choices. All of this in order to offer a great user experience that actually helps the user make decisions about due dates, and ultimately get things done.</p> <p><br><br> </p>
    <table width="100%"> <tbody>
    <tr> <td> <a href="http://www.mightydeals.com/deal/building-and-selling-a-niche-website-from-scratch.html?ref=inwidget" rel="nofollow external" class="bo"><strong>Building A Niche Website From Scratch Video Course – only $19!</strong></a> </td> <td> <a href="http://www.mightydeals.com/?ref=inwidget" rel="nofollow external" class="bo"><br> <img src="http://mightydeals.com/web/images/widget-logo.png" height="40" width="90" alt="How to beat the “paradox of choice” in UI design" style="max-width: 100%; height: auto;"><br> </a> </td> </tr> </tbody>
    </table> <p><br> </p> <a href="http://www.webdesignerdepot.com/2014/04/how-to-beat-the-paradox-of-choice-in-ui-design/" rel="nofollow external" class="bo">Source</a> <br><br><br><a href="http://da.feedsportal.com/r/194479865748/u/49/f/661066/c/35285/s/391c6739/sc/4/rc/1/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479865748/u/49/f/661066/c/35285/s/391c6739/sc/4/rc/1/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/194479865748/u/49/f/661066/c/35285/s/391c6739/sc/4/rc/2/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479865748/u/49/f/661066/c/35285/s/391c6739/sc/4/rc/2/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/194479865748/u/49/f/661066/c/35285/s/391c6739/sc/4/rc/3/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479865748/u/49/f/661066/c/35285/s/391c6739/sc/4/rc/3/rc.img" style="max-width: 100%; height: auto;"></a><br><br><a href="http://da.feedsportal.com/r/194479865748/u/49/f/661066/c/35285/s/391c6739/sc/4/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/194479865748/u/49/f/661066/c/35285/s/391c6739/sc/4/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>“Less is more” is one of the most important minimalistic design principles every designer learns: you read about it a lot, you know it’s really important, but still you might get it all wrong. The...</Summary>
<Website>http://rss.feedsportal.com/c/35285/f/661066/s/391c6739/sc/4/l/0L0Swebdesignerdepot0N0C20A140C0A40Chow0Eto0Ebeat0Ethe0Eparadox0Eof0Echoice0Ein0Eui0Edesign0C/story01.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/43326/guest@my.umbc.edu/59451907dc0d095a5d5901fb1aac968c/api/pixel</TrackingUrl>
<Tag>art</Tag>
<Tag>css</Tag>
<Tag>design</Tag>
<Tag>designing-ux</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>html5</Tag>
<Tag>illustrator</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>oracle</Tag>
<Tag>photoshop</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>todoist</Tag>
<Tag>ui-design</Tag>
<Tag>ui-principles</Tag>
<Tag>usability</Tag>
<Tag>usability-principles</Tag>
<Tag>ux</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 08 Apr 2014 04:15:07 -0400</PostedAt>
<EditAt>Tue, 08 Apr 2014 04:15:07 -0400</EditAt>
</NewsItem>

</News>
