Skip to content

Feed aggregator

Planbox and BrainBank Merge

Scrum Expert - Wed, 07/22/2015 - 17:35
Planbox, a cloud-based agile project management solution vendor, has merged with BrainBank Software the pioneering platform for cloud based collaborative innovation management. The combined company will be called Planbox. BrainBank and its Idealink product will be marketed as Planbox Innovate and the existing solution as Planbox Agile. Ludwig Melik currently CEO of BrainBank will be the CEO of the combined company which will continue the development and support for both Planbox and BrainBank products – all existing agreements and support arrangements remain unchanged. “The combined offering will allow us to benefit ...
Categories: Communities

Ivar Jacobson International Releases Agile Essentials Cards

Scrum Expert - Wed, 07/22/2015 - 16:58
Ivar Jacobson International has released a starter pack of agile practice cards that aid team-based software development by ensuring that core agile team practices are transparent and effective. Each practice contains a small number of cards that provide useful, structured advice on how to apply the practice. In many organizations, arguments rage between software development “experts” and teams on which process framework is best – e.g. Extreme Programming (XP) versus Scrum versus Kanban. Even though agile principles are clear that “no one should tell the team how to do their work”, ...
Categories: Communities

Airport Baggage Claims, Selective Consumers, and RabbitMQ Anti-Patterns

Derick Bailey - new ThoughtStream - Wed, 07/22/2015 - 16:57

One of the patterns found in the Enterprise Integration Patterns book covers the idea of a “selective consumer” – that is, a message consumer that uses some criteria to determine which messages it receives and processes, from a given channel (queue).

Years ago, when I was first working with queueing in WebsphereMQ, I used this pattern to ensure my message consumers only got messages they could handle. It worked well. Fast forward to more recent days, though, and when I tried to do the same thing in RabbitMQ, I found it to be painful and fraught with problems. The pattern of selective consumer turns out to be an anti-pattern in RabbitMQ!

Baggage claim

That doesn’t mean we can’t be selective about what messages are consumed. Instead of using selection criteria, though, we have to turn to the features and capabilities of RabbitMQ to accomplish the same thing – something that is easier and more natural than you might think.

The Core Problem: Selection

RabbitMQ doesn’t have any kind of selection criteria that you can apply to a consumer and a queue. Once a consumer is attached to a queue, it will potentially receive any message from that queue. If you have multiple consumers on a given queue, you don’t know which one will get the message but there’s a possibility that any of the consumers could get a specific message. You have no way of ensuring a specific message goes to a specific consumer, once that message is in a queue. 

To simulate the idea of a selective consumer, you can write code that examines a message once it is received from a queue. If the message cannot be handled by the consumer, the consumer can ‘nack’ the message and send it back to the queue.

This works … to a point. But it introduces some potentially serious performance and thrashing problems in your application.

The Problem, Applied To Airport Baggage Claim

Imagine for a moment, that you’re standing around an airport baggage claim carousel – the kind of carousel where bags ride conveyor belts around and around, waiting for people to grab them.

You stand there, hoping to find your bags quickly – but they never show up. After a few minutes of seeing other people’s luggage go by, you look toward the opening from which the luggage is pouring out. What you see is utterly dumbfounding – but it explains why you haven’t seen your luggage in front of you.

Every time a piece of luggage comes out of the conveyor belt, some one looks at it to see if it belongs to them. If it doesn’t, they don’t let the bag continue to ride around the carousel. Instead… THEY THROW IT BACK! Down in to the depths of the luggage loading system it goes – to be put at the end of the line, waiting to be stuck on the conveyor belt again!

This is MADNESS! Why would anyone toss these bags back to the end of the line, instead of letting them ride the conveyor belt?!

WAIT! Is that your bag, there? YES! … NO! SOMEONE GRABBED IT AND TOSSED IT BACK!!! Now you have to wait for it it come back out and hope no one else checks it before it gets to you again. AAARRRGGGHHH!!!! 

Selective Consumer: The Airport Luggage Anti-Pattern

Using code to selectively check a message, determine whether or not the current consumer can handle it and ‘nack’ it back to the end of the queue is exactly like having your luggage thrown back to the end of the line in the baggage claim. 

If you have multiple consumers attached to a queue, you are potentially at the whim of every other attached consumer. If one of the other consumers consistently picks up your message and tosses it back to the end of the queue, you’ll never get your message and never be able to process it. The queue will continuously thrash as the message is received, examined and rejected … over and over and over again. 

Don’t do this. 

Solving The Selection Problem With Routing

RabbitMQ doesn’t allow you to apply selection criteria to a queue, for a consumer. Instead, you have to assume that any message consumer attached to a given queue can handle any message delivered to that queue. To prevent consumers from receiving the wrong message, then, use routing keys to only send messages to a queue with consumers that can handle the message. 

If you have a consumer that knows how to handle “enroll student” messages, then you should have a queue for “student.enroll” (or similar). Each consumer that attaches to this queue must be able to handle “enroll student” messages appropriately. If the consumer cannot handle that message, it should not attach to that queue. 

Patterns And Practices: Apply With Care

The Enterprise Integration Patterns book is still the source of knowledge for working with messaging systems and message based architectures. But that doesn’t mean you can carte blanche apply these patterns as-is with every messaging system and message broker out there. RabbitMQ, for example, does a great job of including many of the patterns and practices found in this book. That doesn’t mean RabbitMQ applies all of these patterns in the way the authors of the book describe, as you’ve already seen. 

To get a better understanding of how the most common and most important of the Enterprise Integration Patterns apply to RabbitMQ, check out my RabbitMQ Patterns email course / ebook. In here, you’ll find a wealth of experience in applying messaging architecture and patterns to RabbitMQ and application design – enough knowledge to help you get up and running, applying these patterns effectively with RabbitMQ. 

 

 

Categories: Blogs

How to Improve Productivity with DevOps & SAFe

TV Agile - Wed, 07/22/2015 - 16:08
DevOps and SAFe adoption is not easy. This session will discuss a real world DevOps/SAFe transformation and the lessons learned by exploring how a Fortune 100 company transformed from a traditional software shop to an Agile organization. Video producer: http://devopsenterprise.io/
Categories: Blogs

Pitfall of Scrum: Assigning Tasks

Learn more about our Scrum and Agile training sessions on WorldMindware.com

Even though the concept of self-organizing teams has been around for a long time, still some people think that a project manager or team lead should be assigning tasks to team members. Don’t do this!!!  It is better to wait for someone to step up than to “take over” and start assigning tasks.

Assigning tasks can be overt or subtle.  Therefore, avoid even suggestions that could be taken as assigning tasks. For example, no one should ever tell a Scrum Team member “hey! You’re not doing any work – go take a task!” (overt) or “This task really needs to get done – why don’t you do it?” (semi-overt) or “Would you consider working on this with me?” (subtle). Instead, any reference to tasks should be to the team at large. For example it would be okay for a team member to say “I’m working on this and I would like some help – would anyone help me?”

In the Scrum Guide, a partial definition of self-organizing is given:

Scrum Teams are self-organizing….. Self-organizing teams choose how best to accomplish their work, rather than being directed by others outside the team.

A more formal definition of the concept of “self-organizing” can be found here:

Self-organisation is a process where some form of global order or coordination arises out of the local interactions between the components of an initially disordered system. This process is spontaneous: it is not directed or controlled by any agent or subsystem inside or outside of the system; however, the laws followed by the process and its initial conditions may have been chosen or caused by an agent.

The key here is that there is no single point of authority, even temporarily, in a self-organizing team. Every individual member of the team volunteers for tasks within the framework of “the laws followed by the process” – namely Scrum. Scrum does define some constraints on individual behaviour, particularly for the Product Owner and the ScrumMaster. People in those two roles have specific duties which usually prevent them from being able to volunteer for any task. But all the other team members (the Development Team) have complete freedom to individually and collectively figure out how they will do the work at hand.

What If One Person Isn’t Working?

People who are managers are often worried about this.  What if there is one person on the team who just doesn’t seem to be doing any work? Isn’t assigning tasks to this person a good thing?  Scrum will usually make this bad behaviour really obvious. Let’s say that Alice hasn’t completed any tasks in the last four days (but she does have a task that she volunteered for at the start of the Sprint). Raj notices that Alice hasn’t finished that initial task. An acceptable solution to this problem is for Raj to volunteer to help Alice. Alice can’t refuse the help since Raj is self-organizing too. They might sit together to work on it.

Of course, that might not solve the problem. So another technique to use that respects self-organization is to bring it up in the Sprint Retrospective. The ScrumMaster of the team, Sylvie, chooses a retrospective technique that is designed to help the team address the problem. In a retrospective, it is perfectly acceptable for people on the team to be direct with each other. Retrospectives need to be safe so that this kind of discussion doesn’t lead to animosity between team members.

Remember: everyone goes through ups and downs in productivity. Sometimes a person is overwhelmed by other aspects of life. Sometimes a person is de-motivated temporarily. On the other hand, sometimes people become extremely engaged and deliver exceptional results. Make sure that in your team, you give people a little bit of space for these ups and downs.  Assigning tasks doesn’t make a person more productive.

What If There is One Task No One Wants to Do?

Dig deep and find out why no one wants to do it. This problem is usually because the task itself is worthless, frustrating, repetitive, or imposed from outside without a clear reason. If no one wants to do a task, the first question should always be: what happens if it doesn’t get done? And if the answer is “nothing bad”… then don’t do it!!!

There are, unfortunately, tasks that are important that still are not exciting or pleasant to do. In this situation, it is perfectly acceptable to ask the team “how can we solve this problem creatively?” Often these kinds of tasks can be addressed in new ways that make them more interesting. Maybe your team can automate something. Maybe a team member can learn new skills to address the task. Maybe there is a way to do the task so it never has to be done again. A self-organizing Scrum Team can use innovation, problem-solving and creativity skills to try to over come this type of problem.

And, of course, there’s always the Sprint Retrospective!

Why Self-Organize – Why Is Assigning Tasks Bad?

Autonomy is one of the greatest motivators there is for people doing creative and problem-solving types of work. The ability to choose your own direction instead of being treated like a mushy, weak, unreliable robot. Motivation, in turn, is one of the keys to creating a high-performance state in individuals and teams. The greatest outcome of good self-organization is a high-performance team that delivers great work results and where everyone loves the work environment.

Assigning tasks to people is an implicit claim that you (the assigner) know better than them (the assignees).  Even if this is true, it is still easy for a person to take offence.  However, most of the time it is not true.  People know themselves best.  People are best at assigning tasks to themselves.  And therefore, having one person assigning tasks to other people almost always leads to sub-optimal work distribution among the members of a team.

The ScrumMaster and Assigning Tasks

The ScrumMaster plays an important role in Scrum.  Part of this role is to encourage self-organization on a team.  The ScrumMaster should never be assigning tasks to team members under any circumstances.  And, the ScrumMaster should be protecting the team from anyone else who is assigning tasks.  If someone within the team is assigning tasks to another team member, the ScrumMaster should be intervening.  The ScrumMaster needs to be constantly aware of the activity on his or her team.

I have added a video to YouTube that you might consider sharing with ScrumMasters you know about this topic:

This article is a follow-up article to the 24 Common Scrum Pitfalls written back in 2011.

Try out our Virtual Scrum Coach with the Scrum Team Assessment tool - just $500 for a team to get targeted advice and great how-to informationPlease share!
facebooktwittergoogle_plusredditpinterestlinkedinmail

The post Pitfall of Scrum: Assigning Tasks appeared first on Agile Advice.

Categories: Blogs

A Subtle Benefit Of ES6 Arrow Functions With Backbone/Marionette

Derick Bailey - new ThoughtStream - Tue, 07/21/2015 - 19:56

I started a new Backbone/Marionette application this week, and decided to put Babel in place so I can use ES6 features (if you want an introduction to Babel / ES6 features, check out my WatchMeCode series on ES6). I honestly wasn’t sure what benefit I would get, at first. I’ve been playing with ES6 for a while now, but have not yet found the “AHA!” moment that makes me really want to use it everywhere.

What I have found, however, is a subtle benefit of using arrow functions with Backbone/Marionette, that makes me smile every time.

Managing “this” With Arrow Functions

One of the nice features of arrow functions is the ability to manage “this” in the function being executed. Arrow functions use lexical scoping to ensure “this” is maintained based on the context of the function being called (see this WatchMeCode episode on arrow functions for more details). 

In short, that allows me to take this Backbone/Marionette code:

and turn it in to this:

The difference is small… it’s a bit subtle, if you’re not looking for it. But it’s right there on line 5.

Subtle, And Important

The difference of manually specifying “this” as a parameter to the event handler, vs having it managed for me through the arrow function is important in my mind. It prevents me to having to manually manage and manipulate the value of “this” in many circumstances. And while this isn’t the “AHA!” moment that makes me swear ES6 is the greatest thing to happen to JavaScript, it does provide enough value that it warrants the additional layer of BabelJS transpilation in my mind.

Categories: Blogs

Video: Sprint Zero is Not Part of Scrum

Learn more about our Scrum and Agile training sessions on WorldMindware.com

Find out why Sprint Zero is a bad idea, and what you can do instead!

More Scrum and Agile videos to come!  Please subscribe to our WorldMindware channel.

Try out our Virtual Scrum Coach with the Scrum Team Assessment tool - just $500 for a team to get targeted advice and great how-to informationPlease share!
facebooktwittergoogle_plusredditpinterestlinkedinmail

The post Video: Sprint Zero is Not Part of Scrum appeared first on Agile Advice.

Categories: Blogs

Five Tips for Improving Communication

Agile Management Blog - VersionOne - Tue, 07/21/2015 - 14:30

Communication is the key to solving problems and successfully collaborating, but many of us still have difficulty communicating with particular team members. Why?

Because the words we use mean different things to different people in different contexts.
Matt Badgley, an agile product consultant at VersionOne, recently gave a presentation at Agile Day Atlanta about communication techniques you can use to solve problems and improve team meetings.

MattBadgley_550x309

VersionOne: Why is it important to focus on the words we use?

Matt: We all know that collaboration is the key to success. Ultimately, solving a problem is generally done by people talking to each other and working things out. Solving problems often happens inadvertently, through conversations.

So that’s why communication is key, and communication is made up, of course, of verbal and nonverbal cues. The same goes for the role of ScrumMaster. So, if you are in the role of product owner or ScrumMaster and you’re not good at facilitating communication, you are not going to be successful. So that’s why it’s really important.

When you actually talk about what words mean, you will find that certain words in certain organizations trigger emotions. They are bad words. They are basically four-letter words that are emotional for people. So you have to be aware of that. You will also find that there are some terms that mean one thing in one context and something totally different in another context. For example, epic is a word we use all the time in agile. And even the word project means different things, and it actually evokes different feelings in people.

VersionOne: In your presentation you shared some fun facts about communication – can you share those with us?

Matt: One of the most interesting statistics is that women speak roughly twenty thousand words per day on average, while men speak on average seven thousand words per day, and we all have around twenty-five thousand words in our active vocabulary.

Generally, we say between one hundred to one hundred and seventy-five words per minute, although we can listen to up to eight hundred. That is why we can often eavesdrop on other people’s conversations and gain insight. Our conscious minds can only process about forty bits of information per second, which includes colors and things like that. However, our subconscious mind, which deals with our motor skills, processes around eleven million.

One last little fun fact: the word that has been shown through studies of the brain to be the most dangerous in the world is the word no – probably because we learn that word at a very early age and get our hands slapped. So if you say no in a conversation, that instantly turns the context of the conversation around, or changes the tone. This just goes to show that the actual words we use are often undervalued and can mean so much more.

VersionOne: What are some of the ways you suggest for people to solve that problem?

Matt: In my presentation I make five suggestions.

1) Don’t redefine the obvious.

For example, when talking about requirements, we often use the word feature or capability. Now the scaled agile framework refers to requirements as a business epic or a feature epic. You’ll hear different terms that people throw out, just simply to change the term. So, be very deliberate on whether or not you need to change a word or not.

2) Be deliberate and intentional.

If you make the decision to change a term, be deliberate and intentional about using it. For example, the Spotify model uses the word squad rather than team. Squad makes you think of the military or a small group that is a subset of a sports team. A team is a bigger composition, but a squad is a smaller and more intentional group of people. By redirecting and changing people to use that term, it has some underlying meaning that’s beyond the word team.

3) Be aware of biases around a word.

Bias is a preconceived feeling around certain words. A funny one to use is the word ScrumMaster. The term master has some bias behind it, some predefined bias that people bring into the room with them. It’s not always perceived how it is meant to be, although ScrumMaster does actually mean the master of the scrum process, the sensei. At the end of the day, that bias can be dangerous. So be aware of the bias.

4) Use domain language.

Use the words that the business uses already. This suggestion goes with number one: don’t redefine the obvious, but also don’t go out of your way to use a word that’s not unique to your industry. Accept and embrace some of the acronyms that are associated with the industry. For example, in the agile industry, we use the term product owner and sprints, so embrace those kind of words.

5) Use visual elements when defining a glossary.

It may sound strange to create a visual glossary, but the idea comes from how we learned words as kids. You learned the word apple because you saw a picture of an apple. Defining ways in which people can not only read the word, but also visualize the word helps things stick.

Check out these posts to learn more about how you can improve your communication by focusing on what words mean.

Categories: Companies

Talking with Tech Leads now available in print

thekua.com@work - Tue, 07/21/2015 - 10:49

Late last year, I announced the release of “Talking with Tech Leads,” which was then available in a variety of e-book formats including PDF, mobi and epub. Although e-books have their place, I know how important it is for some people, to have a real physical book. After all, it’s very difficult to physically gift something to people, when it’s on a tablet, or computer.

Stack of books from Talking with Tech Leads

After some more work on the physical aspects of the book and many draft copies back and forth from the, you can now order your very physical copy of Talking with Tech Leads. You can order copies depending on region including:

What people are saying about the book:

Your book has really helped me find my feet – James

This book is a well-curated collection of interviews with developers who have found themselves in the role of a tech lead, both first-timers and veterans – Dennis

The book is well-organised around a number of themes and I found it very easy to read and to ‘dip into’ for some inspiration / ideas. – Gary

Categories: Blogs

Parallax image scrolling using Storyboards

Xebia Blog - Tue, 07/21/2015 - 08:37

Parallax image scrolling is a popular concept that is being adopted by many apps these days. It's the small attention to details like this that can really make an app great. Parallax scrolling gives you the illusion of depth by letting objects in the background scroll slower than objects in the foreground. It has been used in the past by many 2d games to make them feel more 3d. True parallax scrolling can become quite complex, but it's not very hard to create a simple parallax image scrolling effect on iOS yourself. This post will show you how to add it to a table view using Storyboards.

NOTE: You can find all source code used by this post on https://github.com/lammertw/ParallaxImageScrolling.

The idea here is to create a UITableView with an image header that has a parallax scrolling effect. When we scroll down the table view (i.e. swipe up), the image should scroll with half the speed of the table. And when we scroll up (i.e. swipe down), the image should become bigger so that it feels like it's stretching while we scroll. The latter is not really a parallax scrolling effect but commonly used in combination with it. The following animation shows these effects:

imageedit_9_7419205352  

But what if we want a "Pull down to Refresh" effect and need to add a UIRefreshControl? Well, then we just drop the stretch effect when scrolling up:  

imageedit_7_3493339154    

And as you might expect, the variation with Pull to Refresh is actually a lot easier to accomplish than the one without.

Parallax Scrolling Libraries

While you can find several objective-c or Swift libraries that provide parallax scrolling similar to the ones here, you'll find that it's not that hard to create these yourself. Doing it yourself has the benefit of customizing it exactly the way your want it and of course it will add to your experience. Plus it might be less code than integrating with such a library. However if you need exactly what such a library provides then using it might work better for you.

The basics

NOTE: You can find all the code of this section at the no-parallax-scrolling branch.

Let's start with a simple example that doesn't have any parallax scrolling effects yet.

imageedit_5_3840368192

Here we have a standard UITableViewController with a cell containing our image at the top and another cell below it with some text. Here is the code:

class ImageTableViewController: UITableViewController {

  override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 2
  }

  override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
  }

  override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cellIdentifier = ""
    switch indexPath.section {
    case 0:
      cellIdentifier = "ImageCell"
    case 1:
      cellIdentifier = "TextCell"
    default: ()
    }

    let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! UITableViewCell

    return cell
  }

  override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    switch indexPath.section {
    case 0:
      return UITableViewAutomaticDimension
    default: ()
      return 50
    }
  }

  override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    switch indexPath.section {
    case 0:
      return 200
    default: ()
      return 50
    }
  }

}

The only thing of note here is that we're using UITableViewAutomaticDimension for automatic cell heights determined by constraints in the cell: we have a UIImageView with constraints to use the full width and height of the cell and a fixed aspect ratio of 2:1. Because of this aspect ratio, the height of the image (and therefore of the cell) is always half of the width. In landscape it looks like this:

iOS Simulator Screen Shot 20 Jul 2015 17.27.38

We'll see later why this matters.

Parallax scrolling with Pull to Refresh

NOTE: You can find all the code of this section at the pull-to-refresh branch.

As mentioned before, creating the parallax scrolling effect is easiest when it doesn't need to stretch. Commonly you'll only want that if you have a Pull to Refresh. Adding the UIRefreshControl is done in the standard way so I won't go into that.

Container view
The rest is also quite simple. With the basics from below as our starting point, what we need to do first is add a UIView around our UIImageView that acts as a container. Since our image will change it's position while we scroll, we cannot use it anymore to calculate the height of the cell. The container view will have exactly the constraints that our image view had: use the full width and height of the cell and have an aspect ratio of 2:1. Also make sure to enable Clip Subviews on the container view to make sure the image view is clipped by it.

Align Center Y constraint
The image view, which is now inside the container view, will keep its aspect ratio constraint and use the full width of the container view. For the y position we'll add an Align Center Y constraint to vertically center the image within the container. All that looks something like this: Screen Shot 2015-07-20 at 17.46.25

Parallax scrolling using constraint
When we run this code now, it will still behave exactly as before. What we need to do is make the image view scroll with half the speed of the table view when scrolling down. We can do that by changing the constant of the Align Center Y constraint that we just created. First we need to connect it to an outlet of a custom UITableViewCell subclass:

class ImageCell: UITableViewCell {
  @IBOutlet weak var imageCenterYConstraint: NSLayoutConstraint!
}

When the table view scrolls down, we need to lower the Y position of the image by half the amount that we scrolled. To do that we can use scrollViewDidScroll and the content offset of the table view. Since our UITableViewController already adheres to the UIScrollViewDelegate, overriding that method is enough:

override func scrollViewDidScroll(scrollView: UIScrollView) {
  imageCenterYConstraint?.constant = min(0, -scrollView.contentOffset.y / 2.0) // only when scrolling down so we never let it be higher than 0
}

We're left with one small problem. The imageCenterYConstraint is connected to the ImageCell that we created and the scrollViewDidScroll method is in the view controller. So what left is create a imageCenterYConstraint in the view controller and assign it when the cell is created:

weak var imageCenterYConstraint: NSLayoutConstraint?

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  var cellIdentifier = ""
  switch indexPath.section {
  case 0:
    cellIdentifier = "ImageCell"
  case 1:
    cellIdentifier = "TextCell"
  default: ()
  }

  // the new part of code:
  let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! UITableViewCell
  if let imageCell = cell as? ImageCell {
    imageCenterYConstraint = imageCell.imageCenterYConstraint
  }

  return cell
}

That's all we need to do for our first variation of the parallax image scrolling. Let's go on with something a little more complicated.

Parallax scrolling with Pull to Refresh

NOTE: You can find all the code of this section at the no-pull-to-refresh branch.

When starting from the basics, we need to add a container view again like we did in the Container view paragraph from the previous section. The image view needs some different constraints though. Add the following constraints to the image view:

  • Ass before, keep the 2:1 aspect ratio
  • Add a Leading Space and Trailing Space of 0 to the Superview (our container view) and set the priority to 900. We will break these constraints when stretching the image because the image will become wider than the container view. However we still need them to determine the preferred width.
  • Align Center X to the Superview. We need this one to keep the image in the center when we break the Leading and Trailing Space constraints.
  • Add a Bottom Space and Top Space of 0 to the Superview. Create two outlets to the cell class ImageCell like we did in the previous section for the center Y constraint. We'll call these bottomSpaceConstraint and topSpaceConstraint. Also assign these from the cell to the view controller like we did before so we can access them in our scrollViewDidScroll method.

The result: Screen Shot 2015-07-20 at 21.30.52 We now have all the constraints we need to do the effects for scrolling up and down.

Scrolling down
When we scroll down (swipe up) we want the same effect as in our previous section. Instead of having an 'Align Center Y' constraint that we can change, we now need to do the following:

  • Set the bottom space to minus half of the content offset so it will fall below the container view.
  • Set the top space to plus half of the content offset so it will be below the top of the container view.

With these two calculation we effectively delay the scrolling speed of the image view with the half of the table view scrolling speed.

bottomSpaceConstraint?.constant = -scrollView.contentOffset.y / 2
topSpaceConstraint?.constant = scrollView.contentOffset.y / 2

Scrolling up
When the table view scrolls up (swipe down) the container view is going down. What we want here is that the image view sticks to the top of the screen instead of going down as well. As well need for that is to set the constant of the topSpaceConstraint to the content offset. That means the height of the image will increase. Because of our 2:1 aspect ratio, the width of the image will grow as well. This is why we had to lower the priority of the Leading and Trailing constraint because the image no longer fits inside the container and breaks those constraints.

topSpaceConstraint?.constant = scrollView.contentOffset.y

We're left with one problem now. When the image sticks to the top while the container view goes down, it means that the image falls outside the container view. And since we had to enable Clip Subviews for scrolling down, we now get something like this: iOS Simulator Screen Shot 20 Jul 2015 21.45.44

We can't see the top of the image since it's outside the container view. So what we need is to clip when scrolling down and not clip when scrolling up. We can only do that in code so we need to connect the container view to an outlet, just as we've done with the constraints. Then the final code in scrollViewDidScroll becomes:

func scrollViewDidScroll(scrollView: UIScrollView) { 
  if scrollView.contentOffset.y >= 0 { 
    // scrolling down 
    containerView.clipsToBounds = true 
    bottomSpaceConstraint?.constant = -scrollView.contentOffset.y / 2 
    topSpaceConstraint?.constant = scrollView.contentOffset.y / 2 
  } else { 
    // scrolling up 
    topSpaceConstraint?.constant = scrollView.contentOffset.y 
    containerView.clipsToBounds = false 
  } 
}
Conclusion

So there you have it. Two variations of parallax scrolling without too much effort. As mentioned before, use a dedicated library if you have to, but don't be afraid that it's too complicated to do it yourself.

Additional notes

If you've seen the source code on GitHub you might have noted a few additional things. I didn't want to mention in the main body of this post to prevent any distractions but it's important to mention them anyway.

  • The aspect ratio constraints need to have a priority lower than 1000. Set them 999 or 950 or something (make sure they're higher than the Leading and Trailing Space constraints that we set to 900 in the last section). This is because of an issue related to cells with dynamic height (using UITableViewAutomaticDimension) and rotation. When the user rotates the device, the cell will get its new width while still having the previous height. The new height calculation is not yet done at the beginning of the rotation animation. At this moment, the 2:1 aspect ratio cannot exist, which is why we cannot set it to 1000 (required). Right after the new height is calculated it the aspect ratio constraint will kick back in. It seems that the state in which the aspect ratio constraint cannot exist is not even visible so don't worry about your cell looking strange. Also leaving it at 1000 only seems to generate an error message about the constraint, after which it continues as expected.
  • Instead of assigning the outlets from the ImageCell to new variables in the view controller you may also create a scrollViewDidScroll in the cell, which is then being called from the scrollViewDidScroll from your view controller. You can get the cell using cellForRowAtIndexPath. See the code on GitHub to see this done.
Categories: Companies

Neo4j 2.2.3: neo4j-import – Encoder StringEncoder[2] returned an illegal encoded value 0

Mark Needham - Tue, 07/21/2015 - 08:11

I’ve been playing around with the Chicago crime data set again while preparing for a Neo4j webinar next week and while running the import tool ran into the following exception:

Importing the contents of these files into tmp/crimes.db:
Nodes:
  /Users/markneedham/projects/neo4j-spark-chicago/tmp/crimes.csv
 
  /Users/markneedham/projects/neo4j-spark-chicago/tmp/beats.csv
 
  /Users/markneedham/projects/neo4j-spark-chicago/tmp/primaryTypes.csv
 
  /Users/markneedham/projects/neo4j-spark-chicago/tmp/locations.csv
Relationships:
  /Users/markneedham/projects/neo4j-spark-chicago/tmp/crimesBeats.csv
 
  /Users/markneedham/projects/neo4j-spark-chicago/tmp/crimesPrimaryTypes.csv
 
  /Users/markneedham/projects/neo4j-spark-chicago/tmp/crimesLocationsCleaned.csv
 
Available memory:
  Free machine memory: 263.17 MB
  Max heap memory : 3.56 GB
 
Nodes
[*>:17.41 MB/s-------------------------|PROPERTIES(3)=|NODE:3|LABEL SCAN----|v:36.30 MB/s(2)===]  3MImport error: Panic called, so exiting
java.lang.RuntimeException: Panic called, so exiting
	at org.neo4j.unsafe.impl.batchimport.staging.AbstractStep.assertHealthy(AbstractStep.java:200)
	at org.neo4j.unsafe.impl.batchimport.staging.AbstractStep.await(AbstractStep.java:191)
	at org.neo4j.unsafe.impl.batchimport.staging.ProcessorStep.receive(ProcessorStep.java:98)
	at org.neo4j.unsafe.impl.batchimport.staging.ProcessorStep.sendDownstream(ProcessorStep.java:224)
	at org.neo4j.unsafe.impl.batchimport.staging.ProcessorStep.access$400(ProcessorStep.java:42)
	at org.neo4j.unsafe.impl.batchimport.staging.ProcessorStep$Sender.send(ProcessorStep.java:250)
	at org.neo4j.unsafe.impl.batchimport.LabelScanStorePopulationStep.process(LabelScanStorePopulationStep.java:60)
	at org.neo4j.unsafe.impl.batchimport.LabelScanStorePopulationStep.process(LabelScanStorePopulationStep.java:37)
	at org.neo4j.unsafe.impl.batchimport.staging.ProcessorStep$4.run(ProcessorStep.java:120)
	at org.neo4j.unsafe.impl.batchimport.staging.ProcessorStep$4.run(ProcessorStep.java:102)
	at org.neo4j.unsafe.impl.batchimport.executor.DynamicTaskExecutor$Processor.run(DynamicTaskExecutor.java:237)
Caused by: java.lang.IllegalStateException: Encoder StringEncoder[2] returned an illegal encoded value 0
	at org.neo4j.unsafe.impl.batchimport.cache.idmapping.string.EncodingIdMapper.encode(EncodingIdMapper.java:229)
	at org.neo4j.unsafe.impl.batchimport.cache.idmapping.string.EncodingIdMapper.put(EncodingIdMapper.java:208)
	at org.neo4j.unsafe.impl.batchimport.NodeEncoderStep.process(NodeEncoderStep.java:77)
	at org.neo4j.unsafe.impl.batchimport.NodeEncoderStep.process(NodeEncoderStep.java:43)
	... 3 more

I narrowed the problem down to a specific file and from tracing the code learned that this exception happens when we’ve ended up with a node that doesn’t have an id.

I guessed that this might be due to there being an empty column somewhere in my CSV file so I did a bit of grepping:

$ grep -rn  "\"\"" tmp/locations.csv
tmp/locations.csv:11:"",Location

We can now narrow down the import to just the one line and see if we still get the exception:

$ cat foo.csv
id:ID(Location),:LABEL
"",Location
 
$ ./neo4j-community-2.2.3/bin/neo4j-import --into tmp/foo --nodes foo.csv
Importing the contents of these files into tmp/foo:
Nodes:
  /Users/markneedham/projects/neo4j-spark-chicago/foo.csv
 
Available memory:
  Free machine memory: 2.22 GB
  Max heap memory : 3.56 GB
 
Nodes
Import error: Encoder StringEncoder[2] returned an illegal encoded value 0

Yep, same error. Now we can clean up our CSV file and try again:

$ grep -v  "\"\"" foo.csv > fooCleaned.csv
 
# I put in a few real records so we can see them import
$ cat fooCleaned.csv
id:ID(Location),:LABEL
"RAILROAD PROPERTY",Location
"NEWSSTAND",Location
"SCHOOL, PRIVATE, BUILDING",Location
 
$ ./neo4j-community-2.2.3/bin/neo4j-import --into tmp/foo --nodes fooCleaned.csv
Importing the contents of these files into tmp/foo:
Nodes:
  /Users/markneedham/projects/neo4j-spark-chicago/fooCleaned.csv
 
Available memory:
  Free machine memory: 1.23 GB
  Max heap memory : 3.56 GB
 
Nodes
[*>:??-------------------------------------------------|PROPE|NODE:7.63 MB-----------------|LA] 10k
Done in 110ms
Prepare node index
[*DETECT:7.63 MB-------------------------------------------------------------------------------]   0
Done in 60ms
Calculate dense nodes
[*>:??-----------------------------------------------------------------------------------------]   0
Done in 10ms
Relationships
[*>:??-----------------------------------------------------------------------------------------]   0
Done in 11ms
Node --> Relationship
[*v:??-----------------------------------------------------------------------------------------] 10k
Done in 1ms
Relationship --> Relationship
[*>:??-----------------------------------------------------------------------------------------]   0
Done in 11ms
Node counts
[>:|*COUNT:76.29 MB----------------------------------------------------------------------------] 10k
Done in 46ms
Relationship counts
[*>:??-----------------------------------------------------------------------------------------]   0
Done in 12ms
 
IMPORT DONE in 1s 576ms. Imported:
  3 nodes
  0 relationships
  3 properties

Sweet! We’re back in business.

Categories: Blogs

Development Podcasts

Here’s my current podcast development list:

Ruby Rogues is the default Ruby weekly Ruby podcast, plus they cover some non-Ruby topics here and there. It’s going on 4+ years now and still maintains a good degree of relevance.

This is the oldest of the Thoughtbot podcasts. It covers a host of topics including some software management.

The Hanselminutes Podcast

Hanselminutes is my concession to keeping up with the .NET world and perspective. Hansel is very good about not diving deep on MS specific topics too often. And I just love his nearly dead podcast This Developer’s Life.

This has been along forever associated with IEEE. I get the sense as the topics are tending towards less enterprisey that IEEE is finally catching up with the post Agile/Lean software world.

This is a great little technical podcast with two Thoughbotters. They go deep on Rails, but swing into other technologies they’re playing with.

Charles Lowell is a really old podcaster from the Drunk and Retired podcast. His company does a lot of Ember currently, but the often wander off into all sorts of technical topics.

Turing Incomplete is a little gem I found a few months ago. It’s four developers from Philly who talk about what they’re learning each week, recent conference talks, or even cool keyboards.
Categories: Blogs

Agoraphobia: The Fear and Loathing of Open Space Offices

Leading Answers - Mike Griffiths - Tue, 07/21/2015 - 05:00
Agile methods like XP, Scrum and DSDM have been advocating co-located teams in open plan offices now for 20 years. The idea being that since face-to-face communications are the fastest and most efficient, teams should be established to work this... Mike Griffiths
Categories: Blogs

Waterfall is just a strawman?

Is waterfall just a strawman used by Agile evangelists?

"strawman" implies that waterfall is not a real problem, that it no longer exists in the modern world of software development.

I don't really know how to respond to this except to suggest to look a little closer at how most IT organisations actually work.

But perhaps it's just a problem for "enterprises" and not "startups" and Silicon Valley?

There are two extremes that lightweight methodologies were a counter for:

  1. Waterfall
  2. Code and fix

Enterprises tend to have the first problem; startups tend to have the latter.

Neither waterfall nor "code and fix" are strawmen within enterprises as they typically have examples of both.

Waterfall is not a strawman but is probably not the problem you're facing as a startup.  That problem is either code and fix and/or the so-called "engineering-driven company" which is why Lean Startup was invented.
Categories: Blogs

Should Engineers Take Scrum Product Owner Training?

Agile Learning Labs - Tue, 07/21/2015 - 00:28

I was recently asked if engineers or other members of the scrum team would get value from a Certified Scrum Product Owner workshop.

Our Certified Scrum Product Owner workshops are designed to build knowledge and skill in three main areas:

  • How scrum works and how to use it effectively
  • How to build shared understanding of the requirements between stakeholders and the development team so that the team builds the right thing
  • How to identify and focus the team’s efforts on the most valuable deliverables

These are topics that every member of a high-performing team should be versed in. Having engineers participate in product owner training helps them understand the context within which they do their engineering work, and helps them understand how to interact better with product owners around topics such as the business value of paying down technical dept.

For products that are extremely technical, engineers usually work closely with the product owner in order to define and refine the user stories. If the engineers lack story writing skills, then the resulting ‘stories’ are often little more than a restating of the architecture and technical design. The problem with this is that many of these ‘technical stories’ need to be implemented before there is anything that is meaningful to the stakeholders. Once those engineers have been exposed to the story writing and splitting techniques in our workshop, they are better able to define/refine stories in such a way that they stay pertinent to stakeholders at all times.

I’ll also point out that all scrum masters should take the product owner training, as scrum masters are the scrum experts that provide guidance to the scrum team and the greater organization. Frequently, the scrum master will be called upon to coach the product owners in the various skills needed to be effective in product owner role.

Cheers,

Chris

Categories: Companies

The Wheel of Change Retrospective

Agile For All - Bob Hartman - Mon, 07/20/2015 - 19:15

Marshall Goldsmith is one of the world’s leading executive coaches. In his book Triggers, Goldsmith introduces a framework for change that he calls the “Wheel of Change“. This framework provides a great template for a Sprint Retrospective or any similar review for a team or larger group.

Wheel-of-Change

 

Draw and label the four quadrants on a whiteboard or poster paper, and have each participant add at least one sticky in each quadrant. Group and label the stickies in each quadrant to see what patterns emerge, then dot vote the groups in each quadrant to see what ideas have the most energy behind them. Pick one specific action for each area of the quadrant, and then get specific about how that change will play out – who needs to be involved, the timeframe for the change, and how you’ll follow up to ensure the change sticks.

Want Help?

If you’d like some help running this retrospective with your team, or to learn other retrospective ideas, contact us. Our passion is helping individuals, teams, and organizations make lasting, meaningful change! If you think this blog post might be helpful to others, please feel free to share it using one of the social media buttons below.

The post The Wheel of Change Retrospective appeared first on Agile For All.

Categories: Blogs

I’m not taking myself seriously…

Indefinite Articles - John Brothers - Mon, 07/20/2015 - 17:29

In a well-written article, John Sonmez writes an article about not taking yourself seriously.   And it’s got some very valid points, ones that I completely agree with – I will make mistakes, and that’s ok.  I will not always get it right the first time, or misunderstand things, and there’s no reason I should expect otherwise.

But I think he misses the key thing that paralyzes me on a regular basis, and keeps me from being more vocal about my opinions and philosophies (of software development, etc).

 

And that is that I don’t want to waste your time.    You only have so many hours on this Earth, and if I write something that doesn’t make sense or doesn’t resonate, I feel bad, because I’ve wasted your time.

 

Now, obviously, this doesn’t matter to most people who post stuff – they are happy to post/write whatever, without a particular care about how it’s received.   And I respect that, from a courage-of-willingness-to-share perspective.   But I also think about the other side – the minutes that the reader is not getting back.

 

Obviously, if everyone felt this way, almost nothing would get written, except by sociopaths and narcissists.     And I think that everyone can agree that a world in which only narcissists and sociopaths shared their opinions would be bad.

So there’s a balance.  I just have to figure out where it is.

 

Categories: Blogs

A Project Management Office (PMO) View of Agile

Scrum Expert - Mon, 07/20/2015 - 15:59
As Agile product and project management approaches are adopted by large organizations, they have to coexist with a typical entity of big companies: the Project Management Office (PMO). A recent report from ESI International explores how the PMO staff views the challenges of implementing Agile in their organizations. The Project Management Office (PMO) is a group within an organization that defines and maintains standards for project management. It is the source of documentation, guidance and metrics on the practice of project management. The ESI survey was conducted online from March to ...
Categories: Communities

R: Bootstrap confidence intervals

Mark Needham - Sun, 07/19/2015 - 21:44

I recently came across an interesting post on Julia Evans’ blog showing how to generate a bigger set of data points by sampling the small set of data points that we actually have using bootstrapping. Julia’s examples are all in Python so I thought it’d be a fun exercise to translate them into R.

We’re doing the bootstrapping to simulate the number of no-shows for a flight so we can work out how many seats we can overbook the plane by.

We start out with a small sample of no-shows and work off the assumption that it’s ok to kick someone off a flight 5% of the time. Let’s work out how many people that’d be for our initial sample:

> data = c(0, 1, 3, 2, 8, 2, 3, 4)
> quantile(data, 0.05)
  5% 
0.35

0.35 people! That’s not a particularly useful result so we’re going to resample the initial data set 10,000 times, taking the 5%ile each time and see if we come up with something better:

We’re going to use the sample function with replacement to generate our resamples:

> sample(data, replace = TRUE)
[1] 0 3 2 8 8 0 8 0
> sample(data, replace = TRUE)
[1] 2 2 4 3 4 4 2 2

Now let’s write a function to do that multiple times:

library(ggplot)
 
bootstrap_5th_percentile = function(data, n_bootstraps) {
  return(sapply(1:n_bootstraps, 
                function(iteration) quantile(sample(data, replace = TRUE), 0.05)))
}
 
values = bootstrap_5th_percentile(data, 10000)
 
ggplot(aes(x = value), data = data.frame(value = values)) + geom_histogram(binwidth=0.25)

2015 07 19 18 05 48

So this visualisation is telling us that we can oversell by 0-2 people but we don’t know an exact number.

Let’s try the same exercise but with a bigger initial data set of 1,000 values rather than just 8. First we’ll generate a distribution (with a mean of 5 and standard deviation of 2) and visualise it:

library(dplyr)
 
df = data.frame(value = rnorm(1000,5, 2))
df = df %>% filter(value >= 0) %>% mutate(value = as.integer(round(value)))
ggplot(aes(x = value), data = df) + geom_histogram(binwidth=1)

2015 07 19 18 09 15

Our distribution seems to have a lot more values around 4 & 5 whereas the Python version has a flatter distribution – I’m not sure why that is so if you have any ideas let me know. In any case, let’s check the 5%ile for this data set:

> quantile(df$value, 0.05)
5% 
 2

Cool! Now at least we have an integer value rather than the 0.35 we got earlier. Finally let’s do some bootstrapping over our new distribution and see what 5%ile we come up with:

resampled = bootstrap_5th_percentile(df$value, 10000)
byValue = data.frame(value = resampled) %>% count(value)
 
> byValue
Source: local data frame [3 x 2]
 
  value    n
1   1.0    3
2   1.7    2
3   2.0 9995
 
ggplot(aes(x = value, y = n), data = byValue) + geom_bar(stat = "identity")

2015 07 19 18 23 29

‘2’ is by far the most popular 5%ile here although it seems weighted more towards that value than with Julia’s Python version, which I imagine is because we seem to have sampled from a slightly different distribution.

Categories: Blogs

Knowledge Sharing


SpiraTeam is a agile application lifecycle management (ALM) system designed specifically for methodologies such as scrum, XP and Kanban.