Monday, November 3, 2014

Transitioning to a professional software development role: part 1

I've spent 14+ years in the software industry in either an IC (individual contributor) role, as an engineering lead, or as a manager. I've worked in both the public and private sector. I've worked at companies as large as 100,000+ people and as small as 19 people. One thing that's been pretty consistent over time is that people first entering into the software industry are ill-prepared for what it means to be a professional software developer. This is equally as true for those coming out of college as it is for those transitioning to software from another industry.

What I'd like to do in this post is outline some of the gaps I've seen in people's preparation and try to pave the way toward helping those interested in software development understand what's expected of them in the industry and how to be prepared.

While the following post will focus on being a good software developer, most of what I outline is applicable to other roles in the software industry such as project/program/product management.

This will be a mult-part post. In part one I will focus on what software development is not.

Being a good software developer is not just being able to code


You're part of a team. Software development isn't just about solving problems with efficient algorithms. You're part of a team which is part of a larger ecosystem. There are product people trying to manage the vision of the software. Their are project people trying to manage the cadence of the software life-cycle. There are other engineers consuming the output of your work. There are internal and external customers trying to use your software to make their lives more meaningful either by being more efficient, participating in some sort of community, or just goofing off playing a game you've written.

Because of this people are relying on you to be an effective communicator. They're relying on you to be effective with time management. They're relying on you to ask for help when you get stuck. They expect you not to go dark. And they're relying on you to help them out when they get stuck.

Essentially you're part of a new tribe, each person having different but overlapping responsibilities. It's important to remember to grow your skills both technically AND with soft skills.

Being a good software developer is not about being clever


One of the biggest mistakes I see newer folks in the software industry make is trying to be too clever in their solutions. Writing software that lasts is about simplicity. Learning to write simple code that clearly communicates it's intentions and intended purpose(s) means that it will be used effectively. Writing code that is clear means that it's readable.

In the software industry you're going to spend more of your time reading other peoples code than you will actually writing code. It's important to learn what it means to write readable code.  I would highly recommend you read the book Clean Code: A Handbook of Agile Software Craftsmanship.

Being a good software developer is not about personal style


Every industry has it's own DSL (domain specific language). That DSL helps people to communicate more effectively within the industry by removing ambiguity and subjectivity. Software development has several different layers of DSLs that it is important to learn.

There are language specific idioms and standards that it's important to be familiar with. There are platform specific standards. For instance standard *nix programs tend to do one thing that can be chained (or composed) with other programs (by piping) to serve some larger purpose. Whereas on the other hand, Windows programs tend to be monolothic in nature and self contained. It's important to know what the standards are for the platform you're working on.

In the same way there are going to be general coding standards that are industry accepted as well as coding standards that are specific your new organization. Your organization will also likely have it's own set of standard tooling for development, deployment, and distribution.

Monday, October 27, 2014

What I've learned in a year

I have now been blogging for one full year. In the past year I've done one installment of the Starting From Scratch series on Android, a series about building a mobile app, 2 Back To The Basics installments covering Binary Trees and Hash Tables, and a whole lot of random posts about software development. So what have I learned over the past year of writing a technology blog.

Ideas aren't as hard to come by as I would have thought


Over the past year I've learned that I have a lot more to talk about than I originally thought I would. When I originally started this blog in Oct 2013 I wasn't sure what the heck I was going to talk about each week. While I wouldn't say I have a book of ideas just laying around, I haven't had trouble coming up with a topic each week. I've probably got about a dozen or so post ideas sitting in the queue just waiting to be written.

A weekly post is a good pace


When I set out to start this blog I wasn't sure on which end of the spectrum my blog was going to fall. One side of the spectrum is a Twitter like blog. The type where you have a bunch of frequent but short (as short as one sentence sometimes) posts. On the other side of the spectrum you have article like blogs. These are blogs that read like a magazine or newspaper article. They're usually chock full of information and other require multiple sittings to read through.

I've found myself somewhere in the middle, slightly skewed more toward article length. I really like doing the multi-part series as well as the little nuggests of things I've learned.

Write a lot and then take time to think


I will usually write three or four blog posts at a time and then stew on my thoughts for a couple of weeks. I feel like it really helps me understand HOW I want to write about WHAT I write. Often I'll have an idea which I think about one way, and then after writing about it will come back and edit it from a different perspective. It's almost been like a conversation with myself.

I still don't know who my target audience is


And I'm okay with that. Sometimes I want to write a really technical article. I'll go deep into an algorithm and feel great about it. Sometimes I want to write a high level about something that's applicable to life outside of software development (even if it's a post about software).

I'm just happy to be writing.

PC marketshare


Over the life of my blog 38% have visited from Windows, 37% have visited from Mac, a smaller than I expected 6% have visited from Linux, and then a hodgepodge of OS's make up the rest (including mobile).

I consume the blogs I follow almost entirely on my mobile devices (90% phone and 10% tablet). So it was a bit surprising to me that the vast majority of blog readers were doing so on desktop machines. I think a lot of this has to do with the sources of my traffic. But I'm not wholly convinced.

I'm just glad to be here


Whether you've been reading this blog from the beginning or this is your first week, I hope you're enjoying what you're finding here. Writing is a form of art to me. I enjoy it, it relaxes me, and it makes me feel connected to humanity.

Thanks for taking the time out of your day to read my blog :)

Monday, October 20, 2014

Conditional logic In Ant

Every so often I find myself needing some conditional logic in my ant build files based on either an automated build property or some property set by current state.

There is an open source library, ant-contrib, which gives you if/else statements in your Ant build files but I tend to not use ant-contrib for three reasons. First, it adds bloat to my project because of the requirement to include it's jar in my projects classpath. Second, you have to mess around with defining tasks in your build files which I just don't feel are very intuitive. Lastly, Ant already includes the ability to perform conditional logic by taking advantage of the Ant target's if attribute.

Performing conditional logic in Ant without an additional library is pretty easy. You simply need to define three targets. The first is the target you want to run in the TRUE scenario. The second is the target you want to run in the FALSE scenario. The third is the target that sets a property (or properties) based on some condition and calls the other targets.

Let's take a look at a very simple build file. This will print This build IS *nix if the isUnix property is set to true otherwise it will print This build is NOT *nix.

<?xml version="1.0" encoding="UTF-8"?>
<project name="example">
    <condition property="isUnix"><os family="unix"/></condition>

    <target name="-unix-build" if="performUnixBuild">
        <echo>This build IS *nix</echo>
    </target>

    <target name="-non-unix-build" if="performNonUnixBuild">
        <echo>This build is NOT *nix</echo>
    </target>

    <target name="build">
        <condition property="performUnixBuild"><istrue value="${isUnix}" /></condition>
        <condition property="performNonUnixBuild"><isfalse value="${isUnix}" /></condition>

        <antcall target="-unix-build" />
        <antcall target="-non-unix-build" />
    </target>

</project>

You can see this in action by copying that file to a machine with Ant on it and running:
$ ant build.
If you're on a Unix like machine it will print This build IS *nix otherwise it will print This build is NOT *nix.

You can test the else logic by overriding the isUnix property at the command line using:
$ ant -DisUnix=false build.

Monday, October 13, 2014

The fallacy of the re-write

I've been in the software industry for a decade and a half and have worked on dozens of projects. Many of the systems that I have worked on were considered legacy systems. As with any system, but even more so with legacy systems, developers will get frustrated with the systems inflexibility. And inevitably this will lead to the developers decreeing that if they could only re-write the system all the problems will be solved. Unfortunately most product owners will eventually give in to these cries and will commission a re-write.

I'm here to tell you today (as both a developer and a manager) giving in to this urge IS NOT going to solve your problems. What it is going to do is grind your production to a halt and make your customers unhappy. This will have downstream effects on the team as the pressure to produce builds and builds and builds.

So why is a re-write not a viable solution?


Re-writes are usually based on a few commonly held (but false) beliefs in the software industry.

  • If we start the project over from scratch we won't carry the problems from the old system into the new.
  • If we start the project over from scratch we can use the latest and greatest technologies that are incompatible with our current technology stack.
  • If we start the project over from scratch we can move faster and produce results quicker.

Why are these fallacies? If we dig a little deeper we will see that a ground up re-write means you are more likely to introduce problems in the new system than you are to solve problems in the old system. What is typically glossed over is the fact that the current architecture is doing a lot of stuff correct. How do I know this? Because it's the architecture that is in production right now running your business.

Let's take them at each of these fallacies one by one.
If we start the project over from scratch we won't carry the problems from the old system into the new.
This statement can really be broken down into two parts. The first part says that there are problems in the architecture that prevent you from extending the code and because you're now aware of those problems you can re-architect the software so that those problems no longer exist. The second part says that you won't carry over existing bugs into the new system. The second part of this statement is really related to the second fallacy, so we'll cover it when we cover that fallacy.

Because it is true that re-writing a system with knowledge of the current architectural problems can help you avoid current pain points most people are quick to accept this statement without challenge. There are many different times in the life-cycle of a product when problems arise. Some arise as bugs when writing the software. These can typically be rooted out with some sort of unit testing. The next class of problems crop up when integrating each of the pieces of the system together. You can create integration tests to help reduce the amount of integration bugs but often there are integration bugs that don't show up in pre-production environments. These tend to be caused by the dynamic nature of content. Because the new system is a re-write of the old system it will be more difficult to use real inputs/outputs from the old system to test the integration of the new system. Because of this you're likely to introduce problems in the new system that don't already exist in the old system. Because the new system won't be in production till it's done, these new architectural problems are not likely to be found till your new system is in production.
If we start the project over from scratch we can use the latest and greatest technologies that are incompatible with our current technology stack.
On the surface this statement is likely true. What this statement hides is similar to what's hidden in the previous statement. New technologies mean new bugs and new problems. Again it is likely that many of these problems won't surface till the new system is in production because, as anyone who has worked in the industry for at least a few years knows, production traffic is always different from simulated traffic. You run into different race conditions and bugs simply because of the random nature of production traffic.
If we start the project over from scratch we can move faster and produce results quicker.
The final fallacy is usually the one that most companies hang their hat on even if they acknowledge that a re-write from the ground up will introduce new bugs and problems and re-introduce existing bugs and problems. The reason is because they believe that their knowledge of the existing system should help them to only solve problems that need to be solved which leads to the system being built much faster.

The fallacy in this statement is more subtle but much more severe than the others. The reason is because until your new system performs all functions of your old system, the old system is superior from a business value perspective. In fact it isn't untill the new system has 100% feature parity with the old system that it starts to provide the same business value as the legacy system, not to mention more business value. Some will try to gain business value from the new system earlier by switching over to the new system before there is 100% feature parity with the old system. But by doing this you're offering your customers less value for the same amount of money, time, and/or investment.

This visual does a good job of illustrating the feature parity problem.



What is the solution then?

Are you saying I'm stuck with my current architecture and technology stack? NO! The best way to upgrade your technology stack is to do an in-place re-write. By doing this you help mitigate the problems presented in a ground up re-write. What does an in-place re-write look like?


By segregating and replacing parts of your architecture you're reducing the surface area of change. This allows you to have a well defined contract for both the input and output of the system as well as the workflow.

In-place re-write has another huge benefit over ground up re-write. It allows you to validate your new system in production as you would any new feature of the system. This allows you to find bugs sooner as well as validate the workflow and feature parity.

Another benefit of an in-place re-write is that you can decommission parts of the legacy system as you go without ever having to do a big (and scary) "flip of the switch" from the old system to the new system.

Most importantly, your customers do not suffer when you do an in-place re-write as you are not ever taking away features from your customers. Even better, you can prioritize giving your customers new features earlier by implementing them on the new system even before you've finished porting the entire old system over.





Monday, October 6, 2014

Starting From Scratch: Android - Creating A Release Build

This week we're finishing the Starting From Scratch series with a look at how to create a release build of our app. I'll show you how to create a release key for your app, secure your release key via encryption, and how to integrate the automatic decryption (and clean up) of your encrypted key during the normal Android Ant build process

Creating a release key for your app


Your key is what identifies your app as being published by you. This is what ensures that only official versions of your app can be released. It's ABSOLUTELY important that noone gets access to your key. DO NOT commit this keystore to your source control repo as is.

Create a release keystore
$ keytool -genkey -v -keystore my.release.keystore -alias myalias -keyalg RSA -keysize 2048 -validity 10000

Securing your release key


Not having the keystore in source control doesn't create a pit of success as you have to manage your key separately from your project. Furthermore, anyone with access to your key can sign an app as you. In order to safely create a pit of success we're going to encrypt our keystore and delete the original so it's not lying around anywhere for someone to abuse.

To encrypt the keystore we'll use openssl and DES3 encryption.
$ openssl des3 -salt -in my.release.keystore -out my.release.keystore.encrypted
$ rm my.release.keystore
The next thing you want to do is put your encrypted keystore in the provisioning directory.
$ mkdir provisioning
$ mv my.release.keystore.encrypted provisioning/

Integrating into the Android Ant build process


Now that we have a key that can be used to sign our applicaiton and we've secured that key from unauthorized access we now need to integrate into the standard Android Ant build process.

The first thing we need to do is create an Ant target that will decrypt the keystore. We also want to create a target to clean up the decrypted keystore immediately after the build. Note that the -decrypt-keystore target supports both prompting the builder for the password or getting the password from an Ant property in the case of an automated release build.

Here's what our encryption.xml file looks like. Create this file in the same directory as your projects build.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<project name="encryption">
    <target name="-decrypt-keystore" depends="" if="isRelease">
        <echo>Decrypting keystore</echo>
        <if>
            <condition>
                <and>
                    <isset property="key.store.password"/>
                </and>
            </condition>
            <then>
                <exec executable="openssl">
                    <arg value="des3"/>
                    <arg value="-d"/>
                    <arg value="-salt"/>
                    <arg value="-in"/>
                    <arg value="provisioning/${assets.keystore}"/>
                    <arg value="-out"/>
                    <arg value="provisioning/release.keystore"/>
                    <arg value="-pass"/>
                    <arg value="pass:${key.store.password}"/>
                </exec>
            </then>
            <else>
                <exec executable="openssl">
                    <arg value="des3"/>
                    <arg value="-d"/>
                    <arg value="-salt"/>
                    <arg value="-in"/>
                    <arg value="provisioning/${assets.keystore}"/>
                    <arg value="-out"/>
                    <arg value="provisioning/release.keystore"/>
                </exec>
            </else>
        </if>
    </target>
    <target name="-clean-keystore" depends="">
        <echo>Cleaning up decrypted keystore</echo>
        <delete file="provisioning/release.keystore"/>
    </target>
</project>
In order to support automated release builds we need to add a few Ant properties to our projects local.properties file. DO NOT CHECK THIS IN TO YOUR SOURCE CONTROL. This file should be restricted as much as possible because it contains the password used to decrypt your keystore. You do not have to put your password in this file. If you don't you'll be prompted to enter your password during the release build.
assets.keystore=my.release.keystore.encrypted
key.store=provisioning/release.keystorekey.alias=myalias
key.alias.password=PASSWORD_YOU_USED_WHEN_CREATING_YOUR_KEYSTORE

key.store.password=PASSWORD_YOU_USED_WHEN_CREATING_YOUR_KEYSTORE
The last thing we need to do is wire up the decryption and cleanup of our key into the existing Android Ant build process. To do this we'll implement the -pre-build, -pre-clean, and -post-build build targets in our custom_rules.xml file. Note that we only want our decryption to happen during a release build. So we're going to define an isRelease property. Our -decrypt-keystore target checks for this property before execution.
<?xml version="1.0" encoding="UTF-8"?><project name="custom_rules">
      <condition property="isRelease"><contains string="${ant.project.invoked-targets}" substring="release"/></condition>

    <target name="-pre-build">
        <antcall target="-decrypt-keystore" />

    </target>

    <target name="-pre-clean" depends="-clean-keystore"></target>
    <target name="-post-build" depends="-clean-keystore"></target></project>
Finally, the last thing we need to do is update our projects build.xml file to include our encryption.xml and custom_rules.xml files.  Add the following two import statements ABOVE the existing ant/build.xml import. For example:
<import file="encryption.xml" optional="false" />
<import file="custom_rules.xml" optional="false" />

<import file="${sdk.dir}/tools/ant/build.xml" />
You can now build a signed release version of your app on the command line with the following command.
$ ant release


Monday, September 29, 2014

Starting From Scratch: Android - Action Bar

This week we're continuing the Starting From Scratch series. Today we're going to take a look at the Action Bar. The action bar UI was first defined in Android 3.x (API 11+). It provided a consistent navigation paradigm for applications as well as a convenient way to present context specific calls to action (like sharing, search, and etc).

Because Android only supported the Action Bar APIs on Android 11+ an open source project called ActionBarSherlock provided support for earlier versions of Android.  ActionBarSherlock is a great project and very useful and eventually Android added a similar Appcompat project to it's v7 support library. While I'm a big fan of ActionBarSherlock I'm going to be using Android's Appcompat project in my example code for consistency.

Creating a project that has an Action Bar.


Setup the support appcompat project as a library. Note, for purposes of this series i'm using android-14 as my target version. You'll want this to match whatever Android version your app is targeting.
$ cd /path/to/android-sdk/extras/android/support/v7/appcompat
$ android update project -p . -t android-14
Make sure that the project.properties file has the android library project property set.
android.library=true
Now that we have our pre-requisites complete let's create an app that will use an Action Bar.
$ cd ~
$ mkdir MyActionBarProject
$ cd MyActionBarProject
$ cp /path/to/android-sdk/extras/android/support/v4/android-support-v4.jar libs/
$ android create project -t android-14 -k com.example. myactionbarproject -p . -n MyActionBarProject -a MainActivity
In order to actually use the support library you need to add a reference to the Android Support Appcompat Library in your project.properties. Note that the path is relative NOT absolute.
android.library.reference.1=relative/path/to/android-sdk/extras/android/support/v7/appcompat
At this point you've got your application setup so that it can use an Action Bar, but it's not using one yet. In order to actually use an Action Bar you'll need to update your Android manifest to use a theme with an Action Bar. This can be done by using either Theme.AppCompat.Light or Theme.AppCompat (dark theme) as the theme of your activity in your AndroidManifest.xml. For example:
<activity android:name="MainActivity"
               android:label="@string/app_name"
               android:theme="@style/Theme.AppCompat.Light">
You'll also want to hint Android that you're going to support an older version of Android. You can do that by adding the following in your AndroidManifest.xml
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
At this point you can compile your app and install it on your test device or emulator and you'll see an Action Bar. Make sure you either have an emulator running or a device attached in debug mode and run:
$ ant clean && ant debug && ant installd

Action Bar Menu


One of the great things about the Action Bar is that you can provide menu items directly in the action bar. This allows you to provide context specific menu options in a place that is convenient and easy for your users to access.

If you are planning on supporting the Action Bar via the Support Library then the first thing to do is to update your Activity to extend ActionBarActivity instead of Activity.

Android provides an Action Bar Icon Pack which you can download and use in your application. Simply copy the resources from the theme your app is using into your res/drawable folders. For this example we'll use the refresh icon.

$ mkdir ./res/drawable-xxhdpi
$ cp /path/to/icons/holo_light/01_core_refresh/drawable-xxhdpi/ic_action_refresh.png ./res/drawable-xxhdpi/
$ cp /path/to/icons/holo_light/01_core_refresh/drawable-xhdpi/ic_action_refresh.png ./res/drawable-xhdpi/
$ cp /path/to/icons/holo_light/01_core_refresh/drawable-hdpi/ic_action_refresh.png ./res/drawable-hdpi/
$ cp /path/to/icons/holo_light/01_core_refresh/drawable-mdpi/ic_action_refresh.png ./res/drawable-mdpi/

The first thing you need to do to add a menu in your Action Bar is to define the menu layout. In my layout I'll be referencing an icon. Here's what our main_activity_menu.xml looks like.

$ mkdir res/menu
$ vim res/menu/main_activity_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:myapp="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/menu_refresh"
              android:icon="@drawable/ic_action_refresh"
              android:showAsAction="ifRoom"
              myapp:showAsAction="ifRoom" />
</menu>

Now that we've defined the Action Bar menu we need to inflate it into our Action Bar. This is done via the Activity's onCreateOptionsMenu event.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_activity_menu, menu);
              return super.onCreateOptionsMenu(menu);
          }

When a user selects a menu item the onOptionsItemSelected method will be called. This method is called regardless of which Menu Item was selected. So you'll need to check the id of the item before you handle the action. Here's an example of handling our refresh action.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if(item.getItemId() == R.id.menu_refresh) {
        Toast.makeText(this, "Refresh selected", Toast.LENGTH_LONG).show();
        return true;
    }

    return super.onOptionsItemSelected(item);
}
At this point you can compile your app and install it on your test device or emulator and you'll see an Action Bar with a refresh menu button. Selecting the refresh button will display message saying Refresh select.
$ ant clean && ant debug && ant installd

Monday, September 22, 2014

Starting From Scratch: Android - Fragments

This week we're continuing the Starting From Scratch series. Today we're going to take a look at Android Fragments. I'll discuss what a Fragment is, the Fragment life-cycle, creating a Fragments options menu, and finally I'll give a few Fragment tips I've found along the way.

What Is A Fragment

Simply put, a Fragment is a way to encapsulate a piece of your applications UI and UI interactions into a reusable set of resources and code. A Fragment is not tied to any particular Activity, but instead can be used within many Activities.

One example of where I've used this modularity in my applications is with Lists. Lists are common in mobile applications and often only differ by what they show. Using Fragments it would be easy to encapsulate creating, displaying, and interaction with a list into a set of reusable code and resources. You could then display multiple lists in a variety of places throughout your app using the same code and resources.

Fragment Life-cycle

The Fragment life-cycle is very similar to the Activity life-cycle we've already gone through in this series. You still have creating, starting, resuming, pausing, stopping, and destroying life-cycle events. But in addition to those you have life-cycle events that are associated with creating your Fragments view and attaching/detaching from an Activity. I'm not going to go through every Fragment life-cycle method but instead will call out two key life-cycle differences from Activities.

The first big difference is in creating the Fragments view. In an Activity this is done via the onCreate method. In a Fragment this is done in the onCreateView method. The onCreateView method is expected to return the view to use with this Fragment. Creating this view is pretty simple, just inflate your Fragments layout using the LayoutInflator passes into this method.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    return inflater.inflate(R.layout.my_first_fragment_layout, container, false);
}

The next difference comes with the onActivityCreated method. The main purpose of this method is to allow the Fragment to restore state. There are two places that state can be stored. The first is internally within the Fragment via a Bundle. The second is in any arguments that were passed into the Fragment by it's composing Activity.

The internal saved state is passed into the onActivityCreated method in the form of a Bundle. The state that was passed in via arguments can be retrieved via a call to the getArguments method. It's important to restore Fragment state using the correct source of information. For instance, if you get the initial state from the Arguments but then update that state and save it in your Fragments Bundle then it's important to have some logic that determines the correct place to get the saved state from.

@Override
public void onActivityCreated(Bundle savedInstanceState)
{
    super.onActivityCreated(savedInstanceState);
    Bundle arguments = this.getArguments();
    if(arguments != null && arguments.size() > 0)
    {
        // set any state that was passed in
        // via the arguements bundle
        this.someVariable = arguments.getString("SomeVariable");
    }
}

Creating Fragments Options Menu

Creating menu items for your Fragment is a four step process. The fist step is declaring your Fragments options menu in an XML file. The second step is declaring that your Fragment has an options menu. The third step is inflating your options menu layout. The last step is handling users selecting an option in your Fragments menu.

First, create res/menu/my_first_fragment_menu.xml. The important thing to call out here is that each menu item needs to have an id. This id is important because there is one method that is called when the user selects a menu item. So we need a way to differentiate the desired action the user wishes to perform.

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/my_menu_item" android:showAsAction="ifRoom"/>
</menu>

Declaring that your Fragment has an options menu is done via a call to setHasOptionsMenu. This call should be made in the Fragments default constructor.

public MyFirstAndroidFragment()
{
    setHasOptionsMenu(true);
}

Inflating your Fragments options menu is done by overriding the onCreateOptionsMenu method. This is done by passing the MenuInflater's inflate method the id of the menu XML file you created. If you want to use an ActionProvider in your Fragment, like the ShareActionProvider, this is the right time to set that provider up.

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
    inflater.inflate(R.menu.my_first_fragment_menu, menu);
    // this is a good time to setup a share action provider
}

Finally, handling the selection of a menu option is done by overriding the onOptionsItemSelected method. This method is called when any menu item is selected. It's a good idea to encapsulate the menu item action into it's own method and just call that method when the item has been selected. It's important to remember to return true in the onOptionsItemSelected method if you did handle the menu item selection.

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    if (item.getItemId() == R.id.my_menu_item)
    {
        this.handleMyMenuItem();
        return true;
    }
    return false;
}

Fragment Tips

Retaining

One thing that often causes people to stumble is putting a video, web browser, or any other stateful object inside a Fragment. The reason is that when the device changes orientation the Activity (and it's child Fragments) are torn down and recreated. This causes problems when the user isn't expecting it. One way to solve this problem is to tell Android to retain the Fragment instance across Activity re-creation. This is done via a call to setRetainInstance. This call should be made in the Fragments default constructor.

public MyFirstAndroidFragment()
{
    setRetainInstance(true);
}

Cross Fragment Coordination

Cross Fragment coordination is done by declaring an interface in your Fragment for any events you want to allow others Fragments to respond to. The Activities that compose your fragment will implement your Fragments interface and can then dispatch messages to other Fragments that it is composing. This allows you to keep your concerns separated correctly by NOT tightly coupling your Fragment with any other Fragment. It's okay to tightly couple your Activity with your Fragment because your Activity is composing that Fragment.