This is a great place to be. Make no mistake about it, this whole series could be seen as a type of funnel. And you made it.
At this point, you should have dashboards about how many users you have starting and finishing the process.
You have a product roadmap that goes out likely a year or so, with new features, tech debt to tackle, and resource requirements.
You’ve got revenue projections and margin projections and hopefully you’ll be able to see Month-over-Month and Year-over-Year growth and things are looking bright.
The balance now is how much, and for how long do you want to continue to enhance what you’re built? The excitement about building the thing has long since faded and the daily numbers, while hopefully still growing won’t scratch that same itch. The same is true of your implementation team, they want to build the next new thing.
Hopefully the success of the product you built has caught the attention of persons or industry and the next attempt you make will have not just the internal lessons you took home, but leads your next effort to greater successes.
So there is where the this series ends, much like the Dark Tower series concludes, it ends where is begins, back on the new thing thing that you want to build, and you will climb that hill once again.
First off, congratulate your team, and yourself, and anyone else tangentially involved. No matter what it took to get to this point I’m sure there were character building moments for everyone. You’ll look back and tell the story of the thing that we built and moments that got you there.
Now one of the tricker phases of the product begins. Because you’ll likely never hit that high you reached in the initial shipping. Everything from here on out is more defined, there will be milestones, or horizons, or versions, whatever you want to call them.
The first one is sometimes called fast-follow. I’d summarize it as the things you’re embarrassed about when you rushed to ship. If you’re being honest with yourself, you called done, but weren’t really happy about it, but you needed that pressure released and so you let a few things go, throwing them in the fast-follow category.
Clean those up before you move on, if you don’t do it now, it’ll never get done. You’ll have nagging issues that follow you to milestone infinity and beyond.
While the team is busy cleaning up the mess you made pre-launch it’s up to you, the product manager, the design representative, and the engineering manager, (Remember the triangle) to get to work.
When you first ideated the product you likely had some research, and some assumptions about what your market wanted. Now you delivered some facsimile of that thing. Did it really address the thing that you thought it would? Metrics are your best friend here. Didn’t include any because you cut them from shipping, oops. Next time, don’t do that, at least include the bare minimum. Ok, time to get ahold of users the old fashioned way.
Assuming you figured out that yes, indeed you built the right thing. Your users / customers are excited about it, they just wish it could do this one related thing. Ok, great. You got your next milestone, find enough overlap of users wanting that next thing and build it.
Now, back to metrics. Assuming you don’t have perfect fit, as referenced about, let’s look to the metrics to figure where things are falling apart. Funnels are usually the go-to representation here. There was some demand for the product, and you have users reaching your product, creating the “top of the funnel”, where are they falling off between there and the action you want them to take. Some examples of those actions might be, Register, Buy something, Subscribe, Tell a Friend, etc.
Address that weakpoint of your funnel, that’s where you want to go next, in this scenario.
Ok, what if there wasn’t users knocking down your door and getting to the top of the funnel. This one is tricky, and more the domain of a marketing professional than your author. But a few category of things exist here, paid and unpaid.
Paid sounds like what it is, your organization has the capital and is commited enough to pay to advertise your product. Awesome. What you need to be tracking now is cost of aquire, and it becomes now doubly important you get the users once in the top of the funnel, through the funnel, and that’s the conversion rate.
Second is unpaid. Less and less so, but Google, and let’s be honest it’s the only game in town, will bring you users that search for “Your Product” some of the time. This is more the case with an existing brand and very difficult to do if you don’t already have some sort of authority. You need to make sure you’re optimized in this area, as it can be free to acquire users. The other free avenue is what is lumped into social, it means getting people excited enough about your product to extend the reach and share, or retweet, or star, or what have you.
So all that’s figured out and we’ve got a product that’s doing what it’s supposed to. Fantastic, that’s when you get to boast about achieving product market fit, and from here on out, things are looking up.
This my friends, is where the action happens. Not a big fan of military metaphors since I don’t have any idea what I’m talking about, but there’s one called no plan survives engagement with the enemy, or thereabouts. Writing this post caused me to look it up and evidently it’s a prussian quote, so it’s been around awhile, seen any prussians lately?
I digress. Bottom line though, whatever you thought you were going to launch with, this is not it. It may share a little or a lot with what you planned. The size of the drift is lessened or heightened by the skill of your implementation team, crossed with the clarity of everyone involved, and the feasibility of the timeline.
Short timeline, you’re cutting scope if you’re smart, nothing else to do.
Team not performing, if you realize it early enough maybe you can change something about the implementation team, otherwise cut scope or wait. And maybe wait forever, perhaps it’s was never possible.
Built the wrong thing, oops. That is on you, leader. This is potentially the worst of the three, you basically lose morale no matter what from here on. You need to now get clarity and explain to the team where it went wrong and what you were really looking for. Hopefully you’re not in this place.
Assuming you’re getting close to launch, and you’re committed to cutting some scope, the question is what. It’s pretty simple, anything that would cause the product to not work, that’s gotta stay. Every other feature, nice to have, design consideration, thing that causes support issues, all are in play.
When is it done? I always say done is a state of mind. More precisely done is when you’re ready to allow somebody outside to the development team to use it. Perhaps there is an executive demo, a group of beta testers, a “bug bash”, and a wide release. This should be encapsulated in an artifact known as a “Launch Plan” which should have dates, actions, and owners on it.
Each of those aforementioned stages could take some amount of time, you might find breaking bugs that simply cause the product to “not work”. Maybe you’ll find some you think, I could live with. Maybe there’s something that will schedule a bug in the future. Monthlong subscriptions looking at you. It’s probably controversial, but I’d make a tradeoff to get the product in the hands of users fully knowing you have a hard deadline to fix some behavior. It’s a known issue and these tend to be easier to fix because once you ship.
Shipping fixes all! Ok that’s an overstatement, but shipping fixes a lot, I compare shipping to an overinflated balloon which represents pressure. Shipping pops that balloon or at least unties the knot which held the fill tube closed allowing for the pressure to release gradually. Let’s explore that in the next section. – Post MVP
Ahh the early building phase. Probably the most objectively enjoyable part of the product development lifecycle. You have your team, you know more or less what you’re building, you were smart enough not to commit to a launch date yet, life is good.
The general positive vibe that accompanies this phase will often cause people to not critically measure the output of the team in this early going. But I emplore you to do so. Is development going faster than you thought originally? Good, means you might actually accomplish this in the timeline you wanted. Is it going according to plan, hmm. Might be cause for concern. But, you can see where I’m going, if you can’t get early wins here quickly when things are at their easiest, it’s going to be difficult as things get harder.
If you are in the second or third buckets, there are a couple of reasons you might not be getting the output you were expecting. The first is on you and the product manager. You didn’t account for complexities, and once the engineering team hit them, you’ve got more scope than you thought. This can lead to your team claiming scope-creep and that’s a quite demoralizing situation that just took away the positivity everyone had for building.
Second is complexity of the task. When the engineering team digs in for the first time, they start challenging the assumptions you and the engineering manager made in the definition phase. These may not pan out, and it’s really impossible to know everything before you start building, so you’ll have some amount of those to work out. A common phrase for those in unknowns. I would argue that the thing you should be most focused on in the early building section of the product development should be driving out unknowns. Once those are accounted for the predictability gained pays off huge dividends.
Third is ramp up. This is probably the best reason things are going slow. There might be some team members or all new to the software stack that you’re using and getting comfortable in the development environment takes some time. But looks for signs that it’s not a ramp-up problem but a much more serious issue, number 4.
Forth is talent. Low general talent levels from some number of team members can be a huge problem. One of the signs of this is simply things assigned to a team member simply don’t get done. There will be various reasons offered and they might even seem plausible. Look carefully though for the same issue for three or more times, and you’ll likely find it’s just a general lack of talent or effort. One of the worst parts about this is that the higher performing team members are stopped from building something that may be critical path, as in blocked from doing their part, by the fact that you’re trying to be inclusive of the lower performers. So in essence you are worse off having the lower performers than no one at all. This last fact was a discovery that look me long in my career to articulate.
Fifth and finally is environment. Some companies get into a point where the cruft of getting things built on top of the existing product is just painful. If a copy change is more than a trivial thing for example, that’s where the problem lies. You won’t likely get this fixed during the build of this particular product, so it’s a tax you’re going to need to apply to all things you build.
In part one we established that you don’t have a team that has the capabilities to build the product you want without input (and to fill in the blanks, let’s be honest you only specified broad strokes of what it is supposed to do).
And now you’re trying to be optimistic but you really have no idea how long this thing is going to take, and whether the team you have can pull it off. Deep breaths. Time to dig in.
At this point one should note that it’s critical that you establish unshakeable rapport with the team you’re trying to lead. If they don’t trust you enough to be honest, ask the right questions, or the wrong ones (If the latter, then you just received a strong signal your need to clarify or repeat yourself). You’re not going to be able to be effectively lead in the manner described throughout this series.
Now you’re going to take stock of what you’re working with, both of the technological process side and the relative strengths of the team members.
For the purposes of the examples that I’m going to write out in the examples below, I’m going to assume what I’ll call the classical setup. 1 Product Manager, 1 Designer, 1 Engineering Manager (Sometimes referred to as Tech Lead, especially if the developers don’t officially report to this person) 5 Developers (+- 2). Different variations could consist of a Quality individual, though sadly in my experience that’s not fashionable anymore, or a Project Manager, but those last two I’m going to omit since often teams don’t have them.
The first three I refer to as the triangle, because the relative strengths of the three are intertwined. A metaphor that might help explain relates to the term “Minimum Viable Product”, which gets thrown around a lot.
In order to get to that MVP I’d argue that you need a minimum viable talent of that triangle. You can have a stronger contributor in either of those three roles be able to make up in essence for less talented in the other roles, especially in this early phase of definition for the product.
For example, you’ve got an amazing Product Manager, has shipped numerous other complex product, maintained amazing relationships with everyone all over your organization, and my all metrics is one of those 10Xers or equivalent. You can then afford a less skilled Engineering Manager, and / or designer, and vice-versa.
All of this falls apart though, if the triangle can’t work together. If you don’t have that fit, your product will suffer, and may fall apart altogether.
Ok, that’s not the case, you have a competent triangle, they’re defining what your MVP is going to be, how long should that process take? Big question, a lot of other literature is going to say it depends, but I’m going give an actual number, no more than one month.
Why one month you might ask? If you can’t define what you’re building in one month, the actual build will likely take over a year, and when your project has a one-year birthday, it’s a failure. Now it might not be considered a failure to the company, but for the purposes of this blog series it is.
Entire companies rise and fall within a year, and you’ve only built this thing? What is the opportunity cost of whatever else you could’ve been building. Would you have taken on this project knowing it was a larger than one year endeavor?
Now what does the definition phase of a product actually look like? What is the deliverable? The actual thing you’re trying to build will of course vary greatly depending on you business, but the actual output should be roughly the same.
By the end of this phase, you’re trying to gather as much information as you can, and have a strong vision of what to build and why. You should be able to explain to team members and stakeholders, in varying levels of detail, tailored to the audience what your product does. Who is the target audience, what is the TAM (Total Addressable Market) if it’s a business, and what success looks like.
The what might be a feature on a established consumer facing website / app, it might be a new one idea, it might be a pivot, it might be a tool to facilitate some business process. Whatever the case may be, you’re going to need to be able to articulate and defend why this product at the expense of any other potential product.
The why usually takes the form of why some party will benefit once the existence of this software happens. One of my favorite game changers, from years back, in the world of software was Google Maps. It largely ushered in the modern “slippy” map, and also showed the world the power of partial refreshing of the document. Move or zoom the map, more map appeared. Clear benefit for all consumers even in the most raw form. Enter an address and instantly see what’s nearby, zoom out and get a broader viewpoint. Past the MVP it became a platform that expanded into turn by turn directions once Mobile became a thing. Once telemetry was fed back into it, you got live traffic, which changed the world.
In the case above, the benefitted party was, more or less, everyone. Obviously most things will have a narrower scope, so let’s go to the other side of the spectrum. When you build some business that has users, there will inevitably be things you didn’t account for and hopefully you have some way for customers to have their problems fixed. A typical solution for this will be a customer service team. You need to build tools for these team members to self-serve. Otherwise your engineering team will get inundated with common “operational” problems, and won’t be able to build wholistic solutions. So the why you might be building those tools that you just found a need for is to enable your customer service team and free up your engineers.
Output. What are the artifacts created to show you have enough definition to proceed? Some sort of “central document” will exist, potentially a product brief, potentially a wiki document with links to the various engineering tickets your product manager creates, and potentially a design wireframe is about what to expect at this point. I’ve also seen a powerpoint deck created, and that be passed around after a meeting where the output of the definition phase is shared.
One note, you want to make sure that if there are going to be common points consistently arising on the product you’re building, it would make sense to call those out in those output documents, so you don’t have to repeat that conversation.
Team built software is much more of an art than anyone gives it credit for. Much of the written information around the process assumes that you’ll be able to figure out a magic formulae that will result in a repeatable process. After years in developing software as an IC (Individual Contributor), learning the different disciplines (Product Management, UI/UX) enough so I can effectively lead, I’ve come to believe it’s the sum of the individuals within the building, and through this series we’ll look at a number of the components that will end in success or failure.
Talent. If you have that, the rest is just window dressing. Organizations sometimes don’t spend much energy defining process and have results, how can that be? Don’t you need a Scrum Master and need to follow the Agile Principles. Or perhaps we need to spend a year writing the perfect requirements (Waterfall)?
There’s a category in the Situational Leadership Model called S4.
Another term that get’s thrown to describe these individuals around is 10X or 10Xer. The gist of this type of talented person doesn’t really need to be given much more than a clear set of requirements and if you have a team full of this type of people, you really just need to explain what you want. A few caveats, it may be possible but early career employees no matter the raw talent, aren’t going to likely be able to do this, because they simply don’t know enough of the pitfalls to avoid falling into one. The minimum I’ve seen here is around 3 years full-time development.
Ok, so you aren’t given, or haven’t created, a team of fully self-sufficient team members, now what? This is where really the job of the leader becomes more important. If you can get the product you want out is going to require you finding the balance point between providing a place where the learning and creativity can happen and grinding out the product you need at the end of the day.
There is surprisingly little information on how to actually build something of use in Cocoa with Rust. I worked my way through it with a lot of perseverance so hopefully I can save you, dear reader some of the frustration along the way. At the end of this Part 1 you’ll have a running app with a button that executes a block of code.
First, a bit of the state of the union that I’ve found. There is an ongoing project to wrap some of the Appkit and Foundation libraries going on over at the Mozilla sponsored Servo project. Specifically, Core Foundation RS. I’ve added a few small PRs to that. That project builds upon the work done by Steven Sheldon’s Rust-Objc
Ok, let’s get started. As with most things Rust, you’re going to need to to add the relevant dependancies to your Cargo.toml as of this publication
From here let’s copy / paste the hello world example
extern crate cocoa;
use cocoa::base::{selector, nil, NO};
use cocoa::foundation::{NSRect, NSPoint, NSSize, NSAutoreleasePool, NSProcessInfo,
NSString};
use cocoa::appkit::{NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSWindow,
NSBackingStoreBuffered, NSMenu, NSMenuItem, NSWindowStyleMask,
NSRunningApplication, NSApplicationActivateIgnoringOtherApps};
fn main() {
unsafe {
let _pool = NSAutoreleasePool::new(nil);
let app = NSApp();
app.setActivationPolicy_(NSApplicationActivationPolicyRegular);
// create Menu Bar
let menubar = NSMenu::new(nil).autorelease();
let app_menu_item = NSMenuItem::new(nil).autorelease();
menubar.addItem_(app_menu_item);
app.setMainMenu_(menubar);
// create Application menu
let app_menu = NSMenu::new(nil).autorelease();
let quit_prefix = NSString::alloc(nil).init_str("Quit ");
let quit_title =
quit_prefix.stringByAppendingString_(NSProcessInfo::processInfo(nil).processName());
let quit_action = selector("terminate:");
let quit_key = NSString::alloc(nil).init_str("q");
let quit_item = NSMenuItem::alloc(nil)
.initWithTitle_action_keyEquivalent_(quit_title, quit_action, quit_key)
.autorelease();
app_menu.addItem_(quit_item);
app_menu_item.setSubmenu_(app_menu);
// create Window
let window = NSWindow::alloc(nil)
.initWithContentRect_styleMask_backing_defer_(NSRect::new(NSPoint::new(0., 0.),
NSSize::new(200., 200.)),
NSWindowStyleMask::NSTitledWindowMask,
NSBackingStoreBuffered,
NO)
.autorelease();
window.cascadeTopLeftFromPoint_(NSPoint::new(20., 20.));
window.center();
let title = NSString::alloc(nil).init_str("Hello World!");
window.setTitle_(title);
window.makeKeyAndOrderFront_(nil);
let current_app = NSRunningApplication::currentApplication(nil);
current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps);
app.run();
}
}
Give it a go with
cargo run --release
Alright if that worked you should see something similar to this…
For me, that was amazing, no Xcode and we have an app up on OSX, my mind started imagining with the possibilities.
Ok, so to wrap up this tutorial we’re going to create a button that has an action and a target, simple right. Well, in short no. We need to dynamically create all the classes on the OBJ-C side, since we’re going to be mostly just passing messages.
First off, we’re going to create a custom class so that we can place code, objc-rust provides this functionality. Warning though we’re going to be running all unsafe code, as usage of raw pointers is the name of the game.
use objc::declare::ClassDecl;
#[macro_use]
extern crate objc;
fn register_button() {
unsafe {
let superclass = class!(NSButton);
let mut decl = ClassDecl::new("HelloWorldButton", superclass).unwrap();
extern fn clicked(_this: &Object, _cmd: Sel) {
unsafe {
println!("clicked {:?}", _this);
let alert:*const Object = msg_send!(class!(NSAlert), alloc);
let alert:*const Object = msg_send!(alert, init);
let alert_title = NSString::alloc(nil).init_str(&"Hello World".to_string()).autorelease();
let alert_body = NSString::alloc(nil).init_str(&"You Clicked Me!").autorelease();
let _alert_id: id = msg_send!(alert, setMessageText:alert_title);
let _alert_id: id = msg_send!(alert, setInformativeText:alert_body);
let _alert_id: id = msg_send!(alert, runModal);
}
}
let clicked: extern fn(&Object, Sel) = clicked;
decl.add_method(sel!(clicked), clicked);
decl.register();
}
}
Ok, there’s a lot going on there, so let’s break it down. First we’re adding some imports into the file, for the lower level rust-objc dance we’re going to do. Now into the register_button fn. As I referenced before, there’s the unsafe block, get used to those.
Our first bit of interaction with objc starts here. The class! macro instantiates a class of the referenced name, objc must already have that declared, and in this case, it does as part of the standard library, NSButton.
Now some magic here, we’re going to dynamically create a custom class that we can instantiate ourselves later. We’re calling that HelloWorldButton and it’s a descendant of NSButton.
Now that we have a dynamic class let’s add some structure to it, below we declare the external fn that is to be called later, which will cause the below alert.
fn create_button(frame: NSRect, title:String) -> *mut Object {
unsafe {
let button: *const Object = msg_send![class!(HelloWorldButton), alloc];
let button_with_frame: *mut Object = msg_send![button, initWithFrame:frame];
let title_as_nsstring = NSString::alloc(nil).init_str(&title.to_string()).autorelease();
let _title_return: id = msg_send![button_with_frame, setTitle:title_as_nsstring];
let _hello_world_button_msg: id = msg_send![button_with_frame, setTarget:button_with_frame];
let _hello_world_button_msg: id = msg_send![button_with_frame, setAction:sel!(clicked)];
button_with_frame
}
}
This block is hopefully a bit more straightforward, notice the re-use of HelloWorldButton which we registered above, we create the button & add the title. One tricky thing to remember is you need to create an objc string. Finally we’re going to direct objc to point the target and action of the click, this took me a long time to figure out, hopefully this will save someone hours of frustration. the sel! macro is interesting, once you have declared something on a native or custom class, it behaves the same a objc with unlimited parameters separated by “:” tokens.
Finally, let’s put it altogether.
register_button();
let hello_world_button_frame:NSRect = NSRect::new(NSPoint::new( 0., 30.), NSSize::new(20., 10.));
let hello_world_button = create_button(hello_world_button_frame, "Click Me".to_string());
...
window.setContentView_(hello_world_button);
We call the functions we created earlier to register and create, and while this won’t work for a larger app we’re just going to make the button be the contentView for the window at this point. NSButton derives at some point from NSView so it’s all good.
TaxJar for WooCommerce allows you to collect accurate Sales Tax! No more setting rate tables, just plug in your key and go
Visit TaxJar to get your key!
Starting at the Launch Hackathon, I’ve started an app, there I’ve said it, app which I think is a distinct new way of booking and picking a travel itinerary.
It’s still in the formation stages but I think the core of the idea is very sound, and I’m pretty excited about it.