Mar 23, 2015
Last year I wrote a post about two deployment patterns to prevent source language bleed through when using a transaction proxy. If you don't want to click through on the link, source language bleed through can happen when a visitor views a page with text that has not been translated yet. Most translation proxies have an option to use machine translations for untranslated text but this is not always desirable.
In our experience, the "International Snapshot" pattern works very well as long as the customer is willing to freeze their content while the site is being translated. Without a content freeze it impossible to make the site completely translated. You never know when a content editor is going to publish a new string. It is also inefficient because the translators might need to translate text that is only on the site for a few hours. For example, a translator might be sent a task to translate a sentence with a typo that will be corrected in a matter of minutes.
But not everyone is willing to interrupt their publishing flow. Thanks to the wonderful world of content management systems, people are used to being able to publish whenever they want. To accommodate customers who have no tolerance for bleed through or content freezes, we have started to apply a new pattern that I call the "Double International Snapshot." This pattern is identical to the "International Snapshot" pattern but has an added layer of a translation instance which effectively freezes the content for the translators.
In this pattern, you have three instances of the site:
- The Original Site that is serving your source language visitors today. This site can be updated regularly for the benefit of source language visitors.
- A "Translation Snapshot" that is a point-in-time snapshot of the Original Site. This site provides a stable environment for new content discovery and staging translations.
- An "International Snapshot" that is a point-in-time snapshot of the Translation Snapshot. This is the site that your target language visitors will hit through the proxy.
The translation process works like this. When you think it is time to refresh the translated sites, you refresh the Translation Snapshot. This freezes the content for the translators so that they can complete their work without new content constantly appearing. The Translation Snapshot can be finalized and go through all sorts of testing to make sure that it as perfect as it needs to be. Once you are satisfied that the Translation Snapshot is production-ready, you refresh the International Snapshot from the Translation Snapshot. Because the translations for the new content are already in the proxy, there will be no bleed-through.
The Double International Snapshot allows content editors to constantly publish new content to the source language site without compromising the stability of the translation environment. The translated sites can be fully verified for translation completeness and quality before going live. This pattern is an ideal solution for companies that don't want to risk source language bleed through but are not willing to compromise publishing freedom. But these benefits are not without cost, you do need to host three versions of your website and you need to build mechanisms for maintaining these snapshots. The Translation Snapshot site can be relatively low powered because it will get only a limited amount of traffic. If your site is simple and does not have any runtime server-side logic, both snapshots could be static HTML files hosted on Amazon S3. This can be done pretty easily with GNU wget.
Mar 16, 2015
One of the most challenging aspects of being a product manager is that your mind needs to simultaneously exist in three worlds — three different realities: the present, the near future, and the distant future. Let's go through them one-by-one.
- The Present
This is the state of the product that everyone is using right now. To the product manager, however, the present feels like the past because it contains features and characteristics that he thought through long ago. The most relevant function of the present is as a tool to learn more about users and decide what the near future should look like.
- The Near Future
The near future feels like the present because it is the world that the product manager's mind spends most of its time in. The product manager is looking at mockups and prototypes and thinking about the sequence of when to deliver near future features. If you follow lean product development, release cycles are short and the actions are pragmatic and concrete. The picture of the near future is clear enough that it feels like present day. We do weekly releases so the near future can be real this week, the next, or the week after. If you use feature flags, the near future may be the current state for some users.
- The Distant Future
The distant future may not be that far away on the calendar (maybe a few months), but to the product manager, it is science fiction. The distant future never arrives; pieces of it merge into the near future but the rest keeps on being pushed off. Because knowledge and priorities are constantly changing, the product manager can't get too attached to the distant future. More than likely, the product manager is juggling multiple possible distant futures simultaneously in his head. The whole purpose of the distant future is to put the near future into a larger context and to force the product manager to extrapolate where decisions for the near future may ultimately lead.
Your product exists in a different state in each of these parallel universes and you need to know every detail about each of these states because people look to you as the expert. It is hard to keep these details from getting muddled together in your head and harder still to not confuse others as you talk about the product.
The hardest time to avoid confusion is when discussing a product road map. The best approach is to talk about the near future. Stick to three months or less with the details weighted towards the first month. With this horizon you are safe to talk about sequencing and dates but the most important topic is "why?" You are rapidly responding to an opportunity, testing a hypothesis, or incrementally building towards something bigger. The reason for an enhancement should fall into one of those three categories. Describe the distant future as a vision that influences your general direction. Don't commit to details or dates. You just need to paint a picture that shows that the next steps in the journey are worth the effort.
The other time when the three worlds confuse stakeholders is when they request a feature. Often what they ask for fits into a larger vision. For example, they might ask you to fix something that you plan to replace with a different approach. You need to adjust your perspective to their present (which feels like your past) and then take them through time to show your plans for the near future. You might also need to take them forward a few releases more to describe how you want that feature to evolve.
Navigating back and forth across the present, near future, and distant future feels a lot like time travel. It is disorienting when you context-shift into a particular time period and sometimes the past feels a little embarrassing when you come back from the future. Like a hero in a time travel movie, sometimes you need to repair the future by going back into the past. There is never a dull moment in product management. If you think things are boring and routine, you need to get your mind over to where the action is.
Feb 24, 2015
I was recently talking with a friend about how hard it is to find a good Drupal developer. While Drupal is the second-most widely used CMS, finding developers who know how to work with it properly is really challenging. I think there are three reasons for this.
- Drupal is so ubiquitous that most PHP developers have had at least some level of exposure to it.
- You can get a lot done in Drupal without knowing what you are doing.
- Most of the people hiring Drupal developers are not able to evaluate the quality of the work.
In thinking about this, an analogy came to mind:
Drupal is to web development as Powerpoint is to design.
PowerPoint is everywhere. Anyone who knows a little bit of PowerPoint, and can search the web for images, can convince himself that he is an adequate designer (or at least a good visual communicator). But the more you care about design, the more horrifying these amateur presentations are. PowerPoint itself isn't bad. If you do have good design skills, PowerPoint can be an incredibly powerful design tool. But there are more bad designers working in PowerPoint than good designers.
Similarly, Drupal has a huge library of modules that you can install and configure about as quickly as you can drop an image onto a slide. An expert Drupal developer will know what modules to use, have good judgement of when to use them, and have a solid process for testing and managing configurations. A Drupal amateur is unaware when he is creating a mess that is going to create embarrassing situations in the future.
So how do you separate the wheat from the chaff in the Drupal developer ecosystem? I tend to focus on three areas:
- The types of sites the developer worked on. Wrong answer: "I build Drupal sites all the time."
- How the developer finds modules to use. Wrong answer: "I just search for them."
- How the developer manages configurations across environments. Wrong answer: "I just click boxes."
By asking these three questions, I can usually get an idea of expertise and craft that a Drupal developer applies to his work. Happy hunting!
Jan 08, 2015
A few weeks ago, I moved my development team from Skype to HipChat for chat-based collaboration. All the buzz around this new breed of collaboration services (such as HipChat, Slack, and Flowdock) was making me curious. I had used private chat room technology like IRC and Jabber in the past with mixed results. I also used to work for a company that made a product called MindAlign (which looks like it has been frozen in time since 2004). In every case, these services were initially popular and then people drifted away to other tools such as AOL Instant Messenger (AIM), Yahoo! Instant Messenger (YIM), Microsoft Messenger, and Skype. People preferred consumer chat services because you can also use them to communicate with your non-work friends. Nobody wants to run more software on their computer than they need to.
Times have changed. YIM and AIM are basically irrelevant only to be replaced by tools like Apple Messages, WhatsApp, and Viber. But I think that there are bigger differences in play.
Smartphones have conditioned us to multiple channels
Now pretty much everyone runs at least two computers: a workstation on our desk and a personal computer in our pocket (our smartphone). These two computers have different roles. Your workstation is very clearly for work and your smartphone is focused on digital communications. The smartphone has the best chat network of all (SMS because it is ubiquitous) and it is easier to use now that we have a keyboard. The new chat services (WhatsApp, Viber, Apple Messages, Facebook Messenger) are all focused on the smartphone market.
Chat-based collaboration tools like HipChat don't have to compete with personal messaging services. It is easier for them to coexist because they live on separate devices.
Twitter and Facebook have built new habits
Twitter and Facebook have had a major impact on how we consume information. We are now much better at handling rapidly flowing feeds of information. We are less intimidated by the volume and we have built habits around scanning back since we last checked. As senders we have built habits around posting things multiple times for people who access different stretches of the timeline.
These skills make it easier to handle group chat services like IRC and now HipChat/Slack/Flowdock.
Integrations make chat collaboration tools more powerful
I know that IRC bots have been around for ages but the new breed of chat-collaboration tools have an amazing collection of integrations. After setting up HipChat, it was really easy to hook in the other tools that we use: Bitbucket, Codeship, and ZenDesk. Now that I am better at handling feeds, it is nice to have all of these notifications in one place other than my email inbox. My hope is that email can be used less for notifications and just for messages that I need to respond to. That may drive email volume down.
As a distributed team that does better with written communication than voice, we rely heavily on chat. Skype was good for 1 on 1 chats but not so great for group chats because it is difficult to get back into a group chat and scan the latest if you closed the window. With HipChat, many of the conversations that used to be 1 on 1 are in an open forum and there is an open invitation to eavesdrop and chime in. It feels a lot more like an office where people are co-located. We even greet each other when we log on.
But the biggest win is in the integrations. Part of that is having notifications in one shared space. It's like an information radiator
in a physical office. Everyone can see it and, when something changes, everyone can talk about it. For example, when we get a ZenDesk ticket notification, everyone sees it at the same time and we can chat about who is going to take it and how to resolve it.
But there is more to it than centralization. I feel the incentive to write better Git commit messages when I know they will go into the stream. People are naturally more thorough and provide more context when writing for a larger audience. Then, if our continuous integration system (Codeship) raises an error, everyone in the room can get complete context of what the code change was, who did it, and the thinking behind it.
A chat collaboration service like HipChat (or others) has huge advantages over tools like Skype. It is especially helpful for us because we are a distributed team; but even in a co-located work environment, chat collaboration could bring the benefits of an open floor plan without the downside
. If you really want to focus on something, you can mute the conversation by shutting down the app and catch up when you come back up for air.
Jan 07, 2015
In case you noticed something different, I moved this blog back onto the Blogger platform. Actually, Blogger is where Content Here started back in 2004 (Wow! A little over 11 years ago!). Over the intervening years, I converted the site to Wordpress and hosted it on a number of different providers. Some of the formatting shows that the posts are a little worse for wear. And I need to do some theming work. If you notice any other major problems, let me know.
Data ownership and control were the primary reasons for moving off of Blogger. When my website was a core part of my consulting business, $20.00 per month seemed worth it. Now that blogging is back to being a hobby and Google has a "Data Liberation Policy," Blogger makes more sense.
Moving from WordPress to Blogger definitely feels like going against the grain but this article "How to Move Your Blog from WordPress to Blogger" gave excellent instructions plus a good explanation of why you would want to do it.
In addition to great utilities for both Blogger and Wordpress, one of the things that made migration easier was that I hosted all of my images and files on Flickr and other sites. That means that there was less to move.
My experience so far is that Blogger seems like a less cared for part of the Google ecosystem. It's clunky when compared to Wordpress or other web content management systems that I have used. I am sure that Google+ (and before that Google Wave) have consumed most of the attention. I can't imagine that Google would kill blogger, but if they do, there is always Google Takeout.
Dec 10, 2014
Here is a little programming oddity that we ran across yesterday.
onDemand has a number of downloadable Excel reports. To generate a useful Excel file, it is important to tell the Excel library what data type to make each cell. To facilitate this, we had a little utility function called is_float:
That seemed reasonable enough and it worked fine for quite some time. But then we had this customer named Nan (thanks for the business Nan!). The problem with the name Nan is that float('Nan') doesn't return a ValueError like float('Bob'). float('Nan') successfully returns a float object with a value of 'nan.' The reason for this is that Nan, in addition to a being fairly common name (I went to school with a girl named Nan), is Python shorthand for a "Not a Number." Python's float function interpreted the input 'Nan' as an attempt to create a float object with a value of 'nan'. This caused our logic to try to tell the Excel library that 'Nan' was a number and that created an error. Incidentally, we would have had the same problem with someone named "Inf," which is Python shorthand for infinity.
In case anyone is curious, the fix for this was quite simple:
The int function doesn't try to be as clever. It rejects cheeky floats like nan and inf. You learn something new every day!
Dec 08, 2014
Prioritizing is hard when other people's requests fight for your attention. It is stressful. You feel attacked; and when you constantly shift your priorities in response to whoever cries the loudest, you get nothing done and you feel defeated. As hard as it is to prioritize your own time, prioritizing what to improve in a product is even harder. The decisions you make on a product have such a large impact. Living under this stress of competing priorities is the life of a product manager. Here are some tricks that I learned.
Create and publish a model for prioritization.
My prioritization framework looks like this. Being transparent about how you prioritize serves three functions: it sets expectations; it encourages stakeholders to express their requests in terms that you can easily evaluate; and it forces you to adhere to your own rules.
Don't elevate the priority of one request. Push everything else down.
It is easy to fall into a cycle of urgency inflation where each request tries to one-up the others in priority. Hysteria builds and you go into reaction mode as you try to keep up. When I feel like this, I try to visualize calmly but firmly pushing other requests down. You only have so much capacity. The highest priority thing should be whatever you are working on right now. It can't get any higher than that. Everything else will have to wait. It feels empowering to actively push requests down to make room for the one request that cannot be deferred. The alternative is passively accepting every request's own self stated importance. That feels horrible.
Group niggling little things into a single item.
One risk of prioritization is that some of the little things never get done. Individually, these details never get to the top of the stack. But in aggregate, they do matter. User experience is all about the details — sanding down the snags that get in the way of delight. To solve this, I like to group some of these requests together to give them a fighting chance against some of the larger initiatives.
Strive for continuous improvement rather than immediate perfection.
Your application is not perfect today and, no matter what you do, it will not be perfect next month. Rather that succumbing to the pressure of immediate perfection, focus on continuous improvement. One of my favorite articles about product management is "Make it Suck Less." While this sounds like an overly humble goal, software would be a whole lot better if every application was managed on this principle. Besides, if you achieved perfection, your job as a product manager would be over.
Take a moment to celebrate your achievements.
After you launch a new feature, resist the temptation to immediately jump to the next thing. Get closure by reflecting on what you accomplished. This will help in two ways: it will get you off the treadmill for a moment to enjoy your success; and it will allow you to evaluate what efforts have yielded the greatest impact so that you can be even more effective with your prioritization. Personally, I find the best time for this reflection is when reviewing release notes before publication and when preparing for a team retrospective.
These practices work for me in product managing my own time. Hopefully you will find them useful too.
Sep 22, 2014
I do a lot of code reviews. On average, I probably spend an hour a day looking at diffs. I find this an efficient use of time because I frequently spot bugs that wouldn't be revealed by regular testing. I can also prevent implementations that will create obstacles as we progress through the road map.
One of the anti-patterns that I have started to notice is what I call the "Too DRY Anti-Pattern." For the uninitiated, DRY stands for "Don't Repeat Yourself". It is a primary tenet in one of my favorite books: The Pragmatic Programmer: From Journeyman to Master
. Keeping your code DRY means using methods and functions rather than copying and pasting code and not storing the same information in multiple places. I have written about DRY in terms of content management in this blog before.
The Too DRY anti-pattern starts with the good intention of keeping the code DRY. The developer creates a function or method to avoid having the same code exist in lots of places. However, over time the developer starts to use that function in places that do not quite fit. The function gets more parameters and has increasingly complex internal logic to control its behavior in different cases. Too DRY functions are easy to spot. They have lots of intricate if-then logic that try to address a wide diversity of usage.
A counter-weight to the Too DRY anti-pattern is the Unix philosophy of doing "one thing and doing it well." When you run into a Too DRY function, use the Unix "one thing" philosophy to break it down. Perhaps create smaller functions that do specific elements of the larger Too Dry function and then have different functions that use those building blocks in different ways. Also, repeating code isn't always a bad thing if the code is small and performs a discrete function. For example, if you have some code that creates an object and sets its properties, it is OK to have similar instances of this logic if the properties need to be set to different values.
Like all things, best practices need to be applied thoughtfully rather than as rigid rules. So keep your code DRY, but not at the expense of simplicity.
Sep 11, 2014
A few months ago we announced the availability of the Lionbridge onDemand Public API. While there are many translation APIs in the marketplace, I think that ours is the most comprehensive. Most translation APIs offer one level of translation quality (for example, machine translation or crowd translation or professional translation). The onDemand API allows you to select a translation type that meets your needs. This means that you can integrate with one API and give your customers lots of options. We also support many different content types. For example, we can translate videos as well as basic documents. Lastly, we offer different payment options. The end customer can pay themselves or the money can flow through our integration partner. I think these differentiators are responsible for the rapid adoption we are seeing. We already have around ten third party integrations in production or nearing completion.
Personally, this has been a huge learning experience. While I have used many APIs and even helped developed a couple, this is the first time that I designed one from a blank page. The sheer number of approaches, options, and details that you face is enormous. And although the biases formed from personal experience are important, what really matters is the developer audience — not just in the decisions you make but also how you support them.
I hate the term best practice but here are some of the things we got right. I must admit that we didn't always land on all of these practices the first time but when we adopted them, we definitely saw results.
Build visibility through success. It is not easy to bring attention to your API. But one thing that we did not do is invest in marketing hype to get the word out. The person who will be choosing what API to use is a developer who is less easily swayed by traditional B2B marketing tactics. The best case is to make your integration partners successful and build visibility that way. I love to hear our early integrations talk about their translation feature. The better we can make the developer experience (through reliability, documentation, support, and service quality) the more quality relationships we will build. I would much rather see a positive mention in Stack Overflow (not there yet, but I can dream!) than a bunch of paid search ads.
- Learn from others. When first designing the API, I drew inspiration from other APIs that I liked to use. I also found great information from George Reese's The REST API Design Handbook.
- Get feedback. When first designing the API, I had the benefit of knowing who the first customers would be. I wrote the initial specification in a Google Doc and invited feedback. The first partners caught some important omissions and had some great ideas too. I also had different developers review the specification before development started.
- Be pragmatic about change. An API is a contract. It shouldn't change. However, in the early going there were a few cases where it made sense to change the specification. This was inconvenient and awkward for developers who are starting their integrations. However, it was much less painful than making changes later when the install base is bigger and changes would break working systems. Managing these changes requires a lot of humility (admitting you are not perfect) and effort to rebuild trust. Once the lead integration partner was getting close to being feature complete, however, we did lock down the version of the API and saved our changes for subsequent versions. Since the initial launch of the API to our beta partners, we have launched another version and are now working on a third. We handle versioning with an HTTP header so it is easy for a client application to update the version to get access to the new feature.
- Hire your first client. While any early beta customer will need to accept some level of instability, you don't want to risk a partnership with your earliest growing pains. For this reason, we hired a contract PHP programmer to develop and test code samples for working with the API. This external developer had no more access than a true partner developer would have. The experiences of this developer gave tremendous insight. It exposed ambiguity in the documentation where the API implementer interpreted different meaning than an external reader. It revealed cases where the test passed but externally developed code didn't work.
- Give client developers a plan of action. Like with most API's the hardest part of working with the onDemand API is authentication. For this reason, we recommend a development sequence that starts with the easiest API: List Services. We also wrote up a quick tutorial with a code sample to help. For our beta developers, we created a project plan template that developers could follow. It contained tasks for integrating with the various features and rough time estimates. I was surprised to learn how much the developers liked this. Personally, I hate being given a project plan that I had no input over.
- Provide fanatical support. Even though I love software development, I am the first to admit it can be frustrating. It is easy for developers to get bogged down and stuck. The smoothest implementations we have had were when the dev team actively engaged the client developers. I admit that sometimes I felt like my time was being stretched too thin. But when you think about it, how can you get more leverage than helping a partner use your service and bring you business? I also enjoyed working with external developers. First of all, they are savvier than regular business users so you can rule out silly things like being disconnected from the Internet. Second, it was fun to troubleshoot with them as they sent requests and we inspected what onDemand received. Pinpointing errors can save a client developer a lot of time. This work had the side benefit of improving our error handling to provide more informative responses.
- Treat your development sandbox like production. This should sound obvious but a lot of services that I have integrated with have very unstable developer sandboxes. They are not always available and they have issues that you don't see in production. There is nothing more frustrating than trying to fix your code and realizing that the problem is in an external system you are integrating with. For this reason, we manage the sandbox as a production environment. It gets the same monitoring as a production environment and we release new code to sandbox after it has been in production for a couple of days.
- Test like you mean it. Software is incredibly picky about the slightest detail so API testing needs to be extremely thorough. You can't just verify that you are getting data back. The data you get back needs to be precisely like what is in the documentation. For this reason we do what I call double-blind testing. The development team writes tests that run whenever new code is merged into the integration branch. An external QA team writes and runs tests based on the documentation whenever we have a release candidate. The hope is that having two independent approaches will everything. When it doesn't, we have a major debrief.
If you do it right, an API can revolutionize your business by opening channels that extend your reach. But getting it right requires commitment and attention to detail. If you underperform in any aspect (design, implementation, or support) your program is doomed. You won't always get everything right but if you maintain your focus and address your failures, you can get things back on track.
Sep 05, 2014
We run our corporate marketing sites on Wordpress. It's not the perfect web content management system for us but, as long as we keep things simple, it does the job reasonably well. When we want to do something that Wordpress doesn't comfortably handle, we tend to use an alternative platform such as Marketo, UnBounce, or develop static web pages.
Wordpress is great, but one thing to consider when using it is that you make yourself a target to all sorts of hacker attacks. When planning server capacity, we need to accept that a lot of our traffic comes from bots trying to hack into WP Admin. There are three things about Wordpress that contribute to this.
Wordpress is by far the most commonly used web content management system. According to BuiltWith, 47.90% of CMS powered websites run on WordPress. The second most commonly used CMS is Drupal with 13.10%. Now I know that those statistics are not perfect but it is clear that Wordpress is head and shoulders above the competition when it comes to CMS adoption.
Wordpress is incredibly easy to identify. If you look at the source of any Wordpress generated page, Wordpress's signature is impossible to miss. Moreover, Wordpress makes it really hard to hide these tells even if you wanted to.
Wordpress is the "go-to" platform for people who know nothing about web development or security. While there are plenty of savvy WordPress developers out there, the majority of WordPress sites were built by people with no clue about security and operated by companies with limited technical know-how. Many of these sites were insecure from day one and only got worse as patching and other maintenance practices were neglected.
Put these three facts together and it is obvious why WordPress is the most attractive platform for hackers and botnets to attack. If you are a malicious hacker and want to get the most out of your efforts, you go after the biggest and most vulnerable target. And in that way, WordPress is a lot like Windows. Windows is everywhere because it is the go-to OS for people who just want a computer at a reasonable price. If you walk into a BestBuy/Staples/Costco to buy a computer, you will walk out with a Windows PC unless you have something else in mind. The majority of these computer shoppers know very little about managing their computers. These users will not keep their software up to date and will accept any dialog. Most of us have spent countless holiday hours removing adware, browser bars, and viruses from these computers.
Just to be clear: Wordpress and Windows are not inherently insecure. With conscientious maintenance, both of these platforms can be as safe to use as the alternatives. It as a sign of success for both Windows and Wordpress that they have earned the distinction of being prime targets for hackers. It is also a great opportunity for external software companies to market services to secure these platforms. The Windows security software market is already large and mature. The number of Wordpress security options is growing fast.
So my advice to everyone is to keep on using Wordpress if it meets your requirements. But accept that your site will be a target for hackers and plan for security. Work with Wordpress specialists (not designers who happen to know a little about Wordpress theming). Follow all the advice in the "Hardening Wordpress" page. Look into 3rd party services that help protect your site. Be safe