Today Nolan Frausto writes today about what he calls the "code culture problem:" one colleague pronounced another's code as "shit" and then drags a third colleague into the first's whirlpool of negativity. This doesn't have to be and the answer isn't just to write perfect code all the time.
First, this kind of behavior can't be tolerated. Not one bit. This kind of negativity is, obviously, counter productive for the person emitting it. The bigger problem is that it's contagious and corrosive as demonstrated in the blog post. I'm strongly in favor of teammates having a vigorous disagreement, but it always needs to be based on respect and everyone needs to finish with cool heads. I consider this a big management/culture problem.
Second, to quote Nolan "What does that even mean?" The flavor of this I often hear is that one developer considers another's code to be "messy." I hate this word (and semi-jokingly forbid its usage on my team) because it's lazy, ambiguous and ultimately doesn't mean anything.
Code can have all sorts of problems: it can lack tests, it can have classes with too many responsibilities, it can have overly long methods, it can have duplicated statements, it can have ill-conceived abstractions ... but unless it's got inconsistent indentation, I don't think any of that is "messy." When people use flimsy criticisms like "messy," especially as justification to rewrite that code, you need to challenge that person to provide an argument with substance.
Here are a couple mechanisms that I use to version things. When I say "things," I basically mean software and documents.
Versioning Software Components
When I version software components I use Semantic Versioning. Hopefully you've heard of this and if you haven't, you should go read it right now. Semantic Versioning, also known as "SemVer," lays out what the major, minor and patch version numbers mean in an x.y.z style version number.
As the name implies, this is the go-to choice when you need to give a version not only a unique identifier, but an identifier which contains a lot of semantic data about its relation to other versions of the thing in question.
(A side note: If you use SemVer, when you release your first version, please bite the bullet and start with version 1.0.0. Resist the temptation to start at 0.0.1 unless you've got a really good reason to do so. Nine times out of ten you don't!)
When versioning documents, I don't need a versioning mechanism with (much) semantic meaning. So, I use a simpler convention.
I also stared doing this because I would find that people would always try to infer meaning from an x.y.z style version number--even in the absence of a formal definition of the digits. And anyway, in cases like these I just need a convention which clearly identifies the uniqueness and ordering of versions.
Many years ago I adopted the convention of using revision letters in this situation. I think I saw this being used on hardware documentation early in my career. The full convention I uses is "Rev A," followed by "Rev B" and so on. I usually don't get past "C." Pretty self-explanatory!
Examples of this would include something like "Hiring Plan 2H2013 -- Rev A" or "Budget -- Rev C."
I'm starting to do a lot of hiring again and once again I'm becoming reacquainted with a lot of the things job seekers do (and don't do) that annoy me. I've always said "I should write some blog articles about this in hopes that it will change some people's behavior."
So, here's the first one! I don't offer this as universal advice (though I think a lot of this is good general advice for job seekers.) I think this is good advice for getting hired at a small tech startup. It's definitely good advice if you're trying to get hired by me! :)
To The Matter at Hand
As the title of the post suggests, I get frustrated that most resumes I receive are not accompanied by a cover letter. (And by "cover letter" I mean "cover letter email.") I know this may strike a lot of people as old-fashioned but it really bugs me. Here's why.
With no cover letter, you're putting an enormous burden on me to figure out who you are. In general it's hard to write a resume and most people are not good at writing them. Recruiters have caused people to create resumes that are a jumble of keywords. People either write "War and Peace" or they don't write anything of substance at all.
Over the years, I've developed a bunch of rules of thumb that I used to reject resumes, there are a few specific things I look for that interest me, but frankly, the rest is sort of hit or miss. If you write some actual prose explaining your career history, why you think you'd like to come work for the company, etc. I would find that immensely useful.
Otherwise, I'm left trying to figure out on my own how all the pieces of your history fit together in a way I care about. (Which I'll eventually do, but don't you want to help point out the way? Do you not want me to experience delight at our first meeting?)
Not sending a cover letter shows a lack of effort and genuine interest. I worked hard to craft the best job description I could to attract your attention. I will carefully read your resume. I will spend time prepping for a phone screen with you. And so on.
When you don't write a cover letter, I have no evidence that you've done the same. Given my history of awful phone screens where people have not taken the effort to look at our company website or try the product, I'm pretty comfortable making this assumption.
Really, a resume that shows up on the "careers" mailing list or our resumes tracking system without a cover letter looks a lot like spam. It's impersonal and feels like you're just on the receiving end of a mass mailing.
Sending a cover letter shows that you have a command of written English. The farther along I get in my career the more I realize just how hard it is to communicate with other people. I also realize more and more how much a well-functioning team depends on strong spoken and written communication. ("Hrm, what does this crappy comment in this code mean?") As a consequence, I find myself more demanding that people we add to our team are well equipped to communicate effectively.
So, please, the next time you apply for a job (especially with me!) please write a couple of short paragraphs building a narrative of why you think you're a good fit for the position in question. It doesn't need to be high ceremony--please let your personality come through. It's an easy way to jump to the top of the list!
There's an article, "The Tech Industry’s Darkest Secret: It’s All About Age", by Vivek Wadhwa which I spotted this morning. In it he asserts that all startups are hell-bent on hiring 20-somethings for a pittance and turning their backs on anyone who didn't grow up watching Pokemon cartoons. I've got a slightly different take on this matter.
He's correct in that this is a touchy subject. And since I am a hiring manager at a SaaS startup, let me be clear: we hire smart and emotionally mature people who, via a rigorous and standardized interview protocol, we believe will get things done and thrive at our company. We do not take age, gender, marital status, race, religion and etc. into account when hiring.
This has endowed us with a awesome and diverse technical team. We've ended up providing a significant amount of training to everyone who has joined.
Mr. Wadwha cites this study:
Brown and Linden’s analysis of Bureau of Labor Statistics and Census data for the semiconductor industry revealed that although salaries increased dramatically for engineers in their 30s, these increases slowed after the age of 40. After 50, the mean salary fell by 17% for those with bachelors degrees and by 14% for those with masters degrees and Ph.Ds. And salary increases for holders of postgraduate degrees were always lower than for those with bachelor’s degrees (in other words, even Ph.D degrees didn’t provide long-term job protection).
(Let me say, these are statistics about the semiconductor industry and not the software industry. I don't know if they've got any bearing to software/web startups at all. But let's say they do, just to have the rest of the conversation.)
He then makes this statement:
It may be wrong, but look at this from the point of view of the employer. Why would any company pay a computer programmer with out-of-date skills a salary of say $150,000, when it can hire a fresh graduate — who has no skills — for around $60,000? Even if it spends a month training the younger worker, the company is still far ahead. The young understand new technologies better than the old do, and are like a clean slate: They will rapidly learn the latest coding methods and techniques, and they don’t carry any “technology baggage.” The older worker likely has a family and needs to leave the office by 6 p.m. The young can easily pull all-nighters.
So, I'm not going to debate whether or not employers are doing this. If they are, they're wrong.
(And if they are, so much the better for me. While you're killing yourself finding and then overpaying a 20-something "Rails Ninja" (because I think theses comp numbers aren't right) I'm making a minor investment to turn a great engineer who doesn't know Rails into a great engineer who does know Rails in a scant few weeks.)
However, I would like to recast the above statement not in terms of young vs. old, but in terms of adaptable vs. non-adaptable.
People who are attractive to me as a hiring manager are people who exhibit adaptability, curiosity and industriousness. As a hiring manager reading a resume or conducting a phone screen, the marker for these traits is a history of tinkering around with mobile devices, hardware, open source or some other activity that demonstrates the person has a desire to learn and do.
I'll anecdotally assert that people who went through college in an age of cheap computers, easy high-speed Internet connectivity, a burgeoning ecosystem of free languages and other technology are more likely to exhibit those markers. Because it was cheap and easy! (I might even argue that it also became cool.)
The people who did not enjoy a that kind of environment seem to be less likely to exhibit the markers I mention--but they're not that hard to find! Especially if you're motivated.
Mr. Wadhwa closes with several pieces of advice which may or may not be attractive to you. For folks of all ages who love technology and coding, I'll highlight this one:
Keep your skills current. This means keeping up to date with the latest trends in computing, programming techniques, and languages, and adapting to change. To be writing code for a living when you’re 50, you will need to be a rock-star developer and be able to out-code the new kids on the block. Top developers are always in demand and companies will readily pay top dollars for them.
I'm not sure I'd phrase it exactly that way, but I'll second its spirit. If you're a person who likes to code and you're not already doing something to demonstrate you're an adaptable, curious and industrious person, do it now. Especially if you want to work at an early stage company.
You don't need to write the next Linux or Rails. But you should be spending an hour or two a week on keeping sharp. Think of it like brushing your teeth twice a day and saving for your retirement (except it's more fun!) It will pay off in the future.
I'm working on the next version. The fact that Rails, Formtastic and Bootstrap all changed just as I was starting a new job and a family have made it hard to give the attention it deserved. I will be looking for help with the project going forward. I will communicate more. Thank you to everyone!
The Longer Version
Hello to all of the beautiful people who have used Formatastic Bootstrap over the last 9 or so months. The project has met with more success than I would have ever imagined Thank you!
As you're likely aware, the project has fallen behind these last several months. I want to communicate how things got here, where things are now and how I'd like to proceed going forward.
How We Got Here
In November 2011 I had finished winding down my startup project and while looking for a job, I kept myself busy working on various projects. It was easy to find the time as my week was free and my son could not yet walk (and get himself into trouble!) Also, the mapping between the output of Formtastic and the markup created by Bootstrap was not so dissimilar.
In December 2011, I had the very great fortune to join a startup where I was helping to build the development team and product. Within the next two months, Rails, Formtastic and Bootstrap all underwent major upgrades. I simply did not have time to work on the project as I chased my son and got up to speed at my new job.
In the meantime, several folks took branches and submitted pull requests that provided support the newer versions of Rail, Formtastic and Bootstrap. I thank them for this!
However, even as I was writing the original version of Formtastic Bootstrap I was unhappy with how it was put together and none of the changes that have been offerred address these issues. Of course, no one could know this because I've never stated this publicly.
Where Things Are Now
Through the Summer of 2012 I have been working on Formtastic Bootstrap v2.0. This will support Rails 3.2, Fortastic 2.2 and Bootstrap 2.x.
The progress is going slowly. I only have a couple of hours to work on it every few weeks. I do not have a stated release date. (I thought I would be done by the end of July at one point.)
I will push a branch soon which will have the current state of my work. It will be work in progress (i.e. you shouldn't point your Gemfile at it!) However, you should have some idea of how things are progressing from that branch.
One goal is to try and play more nicely with Formtastic so that it will be easier to respond to the changes made in that project in the future. I am also updating the Formtastic Bootstrap test suite with Formtastic's.
I'm trying to restructure the code so it is clearer how it produces Bootstrap-friendly markup.
The additional challenge is that the mapping between Formtastic's generated output and what Bootstrap is expecting is less clear. It is taking me longer to figure out what to do in each particular instance. (This is made more difficult by the fact I am away from the work for weeks at a time.) Bootstrap has also added a lot more features.
I am actively soliciting collaborators for the project. If you are interested, please get in touch with me. I'm thinking that once the v2.0 release or release candidate arrives, we can help polish it up, add support for additional Bootstrap features, provide better documentation and in general just incrementally keep up with Formtastic and Bootstrap (and of course Rails 4 is on the way...)
I will communicate the status of the project more regularly, sometimes on this blog but probably more often using twitter.
Formtastic Bootstrap has been downloaded on 14,000 times and has over 100 forks on Github. I never in a million years would have imagined I'd put together something so useful! Thank you to everyone who has used it and who has been so patient over the past few months.
I want someone to build a very simple, web-based drawing app that allows multiple people to see what's being drawn in real time. At the push of a button the service emails a jpeg of that drawing to all of the participants
I'd appreciate any pointers to this product. If you want to build it, please contact me. I will pay for this.
For the first time in my career, I'm working with on a daily basis with someone located remotely. It works better than I would have expected. I think this is because we're both native IMers, I finally started using Skype regularly, and, in no small part, because he's a great colleague.
Still, I find we keep postponing certain discussions until our next in-person meeting. I think we're doing this because 1) we believe we'll have more time for these discussions in person and/or 2) because we don't have a white board where we can explain ideas.
My Minimum Viable Solution
I sign up for the World Wide Whiteboard service. I create a new whiteboard session and it gives me a new URL that I can either drop into an email or something like HipChat or Yammer.
When people click on the link, they provide their email (if the service doesn't already recognize them) and they see the whiteboard.
While we're talking on the phone or Skype, we're drawing in the browser. Everyone sees this update in real time. The drawing system is simple. It only needs to support freehand drawing. The drawing background is white and the ink is black. (Maybe there are a couple of other colors, too.) There is an area eraser and an option to clear the whole board.
At any time I can hit a button that will send a jpeg image of the current whiteboard to all of the attendees via email. When I use the whole board erase function I should be asked if I want an image sent at that time, too.
What I don't need or want:
A built-in chat system. Between AIM, gtalk, Facebook Chat and HipChat (and maybe even throw in Twitter) I've already got way too many options for chatting. Besides, we're on the phone when we're using this.
A follow-on to the above point, I don't want any kind of moderation system or other discussion facilitation mechanisms.
I don't need fancy templates or pre-canned shapes. (Probably)
I don't need the ability to store these whiteboards. (Probably)
Extraneous social features.
This product should be drop-dead simple in its appearance and use.
For those who do not know, (read: everyone) A Place Between Us is a tool that will let you and someone you're meeting find a good mid-way point for meeting. You get to pick the type of meeting place, like "coffee" or "thai food."
This was conceived by Aron and me (and then built by Aron) when we were working on a startup in 2007. We were working from our homes and always looking for places to meet each other or other people.
I've just released a new version of Panini, a Ruby gem that generates sentences from a given grammar. This release adds a new derivator that will exhaustively create every sentence in a grammar if called enough times.
grammar=Panini::Grammar.newn_s=grammar.add_nonterminaln_a=grammar.add_nonterminaln_b=grammar.add_nonterminaln_s.add_production([@n_a,@n_a,@n_b])# S -> AABn_a.add_production(['a'])# A -> 'a'n_a.add_production(['x'])# A -> 'x'n_b.add_production(['b'])# B -> 'b'derivator=Panini::DerivationStrategy::Exhaustive.new(grammar)begins=derivator.sentenceputss.join(' ')unlesss.nil?endwhile!s.nil?