tag:blogger.com,1999:blog-29062161023167908742024-03-08T15:41:06.127-08:00Sincerely, Managementbecause I can, even though I don't want toeleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-2906216102316790874.post-27373661339686653492010-08-20T11:33:00.000-07:002010-08-20T11:41:23.362-07:00Bad Ass Web Applications with Forgettable NamesI recently had a string of good luck finding web apps that are well designed and make my job easier (ironically most of them are built on flash). Unfortunately, I can't ever remember their names because they make <b>no sense</b> and I don't use them every day. I was thinking about making a web app to remember them for me, but couldn't find a name that I would remember for that either. And now the purpose of this post is clear.<br />
<br />
I'm very picky and probably try hundreds of new apps a year. I've wasted 10s of hours combing through crap, blah, and broken to get down to these tools. Despite the completely forgettable names, these are the few that don't piss me off:<br />
<ul><li><a href="http://cacoo.com/">Cacoo</a>: Wireframes. The interface reminds me of Gliffy but a little more stylized, hip. If Gliffy is Bill Gates then Cacoo is Steve Jobs.</li>
<li><a href="http://www.colorschemer.com/schemes/">Color Schemer</a>: Ready to go color schemes. It's better than agonizing for hours over color palates.</li>
<li><a href="http://www.gliffy.com/">Gliffy</a>: Online version of visio. I assume this is named after some famous rapper or something. Bling bling bitches.</li>
<li><a href="http://prezi.com/">Prezi</a>: While it's interesting for presentations, I use it for doing architecture diagrams that are deeply nested. I would not object to gliffy and prezi hooking up and birthing a love child. </li>
</ul><div>And that's it. Hopefully google indexes this and takes me to this page the next time I search for "that thing that makes diagrams on the web and is flashy". Index it!</div>eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com1tag:blogger.com,1999:blog-2906216102316790874.post-59156635054655329092010-07-30T15:57:00.000-07:002010-07-30T18:30:06.181-07:00Reality TV: So You Think You Can Startup<div>There is a lot of hype surrounding the startup culture, especially if you are young and fresh out of college. People blog a lot about making your own startup, but rarely about what to consider when joining someone else's startup. This is very different than joining an established company because it's much more likely to fail than succeed. The reality of startups is not the buyout or bust that blogs like TechCrunch make it seem: it is a painful roller coaster of hard decisions, long nights, and a lot of waiting. Oh, the waiting! </div><br />
<div>Well, the waiting has come to an end. Today is the last day of operations at Janus Health. It's a huge bummer to say the least. Following a roller coaster of financing issues, the money well is finally dry. Hopefully this eulogy sheds some light on how things really end in startups, and things to think about before accepting a position at that startup that "have the perfect position for a person with your skills".</div><br />
<span class="Apple-style-span" style="font-size: large;">Backstory</span><br />
<div>Like many developers, I was working a normal job and doing some consulting work on the side. The company was trying to do a proof of concept of online-offline patient management and I was working the technical implementation. After a couple months, I signed up full time as a lead developer, platform specialist, database admin, etc... </div><br />
<div>The next 3 years were insane. I was constantly stressed out, babysitting the system, learning new tech under pressure, and of course reveling in the victory of conquering problems. As the only developer for 2 of those years, I did way more boring code monkey work than I ever imagined. It completely surprised me that startups are the actually the last place to try out new ideas - it's push or perish! </div><br />
<div>The product had become my ill behaved child, my obsession, and a continuous source of drama. I thought about leaving constantly, but who would watch after it if I left? Just like a child, after about 3 years things started to get easy. I had help now. The system was stable and fast, the customers were happy, and we were ready to announce 2.0. Money was coming in, but apparently not enough. </div><br />
<div>This was really the second death. A <a href="http://elizabethleddy.blogspot.com/2010/03/coming-may-2010-at-bar-near-you-there.html">few months ago</a> we were almost dead when a last minute term sheet with a big wig investor gave us enough credibility for a 2 month bridge loan. The deal included a clause saying we wouldn't look for any other investors while the lawyers battled over stock options. 2 months later and 1 month of server costs left in the bank, and the investing company is being acquired. Deal off. No backup funding. Employees cut loose. Customers notified.</div><br />
<div><span class="Apple-style-span" style="font-size: large;">The Real Losers</span></div><div>The people who are the worst off in this situation are the customers themselves. A painful contract termination letter went out two days ago stating that they have 1.5 more weeks to use our services. Switching EMR (Electronic Medical Record) vendors is usually a 3 month task. My heart goes out to them since their workflow will be severely hampered. This is the risk of going with a startup to fulfill a critical business operation - I'm grateful they took the risk and sorry that it will probably scar them for the rest of their IT purchasing life times.</div><br />
<div>On the more positive note, the customers were always happy with the product and seem to be working together to create a grassroots/cooperative maintenance solution of the product. Luckily one of the customers was also a big investor and is willing to leave the source code in it's current installation. I hope they follow through and make the dollars work for them.</div><br />
<div><span class="Apple-style-span" style="font-size: large;">Lessons</span></div><div>It is better for the product to go grass roots anyways. I had an epiphany a few months back about why we were struggling in the first place. The company strategy was to be bought out, and that requires a lot of initial capital and an "enterprisey" take on the healthcare market. However, our customer was not enterprisey at all; they are [mostly] grass roots physicians who truly believe that it's better for the health of people to be taken care of at home*. They choose to take severe cuts in pay and deal with billing hell because they believe in the cause. In that sense, it's important to align with your customers market: a home brew market needs home brew solutions to grow with them, and we didn't want to be small. </div><br />
<div>I didn't think we would always be enterprisey. When I joined the team, I assumed things would change with time (with my influence of course), and we would become more transparent and "open sourcey". I now know this rarely happens, and if I had took the time to sit down and actually read the financial part of the business plan (which EVERY startup should have) I would have known that. </div><br />
<div>After things started going bad, an old friend once told me "some CEO's like to climb mountains, while others like to fly". Most people actually join other peoples startups, and if you are presented with an opportunity you better figure out what kind of passenger you are and what kind of CEO is leading the way. This way, you know how they have the potential to make your life miserable. If that company is climbing mountains, things are slower, the cash pot at the end is less likely and/or a long way away, but you'll be fully aware when things go bad. Flying means you crash into the side of a mountain with no survivors. </div><br />
<div>Reflecting upon the accident it's interesting to reveal what actually caused crashed. I don't think it had anything to do with the product, although I had moments where the choice to not use a stock LAMP or Java solution may have prevented lucrative partnerships.The business model was innovative, perhaps risky. I gasped the first time I learned our burn rate. We were flying in style. A lot of money was spent on licensing that could have been shaved. We needed more employees to grow, but maybe we should have been letting them go. </div><br />
<div>I never took the time to learn things like bridge loan, diluted stock, term sheets, etc... and I sincerely regret it. If you are thinking of joining a startup, take a crash course at your local SBA or sit in on a local college class to learn, especially if you will enter into a decision making role. Heck, even if you aren't going to a startup I recommend it: business accounting is fascinating. In retrospect, there are several key decisions I made that I now wonder if I would have decided otherwise if I had understood the finances better. Contrary to my previous beliefs, its actually accountants that are our overlords, not octopuses. </div><br />
<div>This idea in startups that if you build a great product, eventually you will have great customers and money will just start flowing is absolute horse poo. That meme should die alongside princes saving princesses on white horses. I'm convinced that companies touting this secretly have amazing money wranglers in the background, and should be legally obliged to footnote these claims with "for motivational purposes only". </div><br />
<div><span class="Apple-style-span" style="font-size: large;">Adieu</span></div><div>I couldn't be more grateful for the experience and wish the best to all the people who worked side by side through some truly awful and amazing times, to the clients who tolerated our mistakes as we learned how to steer, and to the investors who believed in the product to begin with. Best of luck to all.</div><br />
<div><span class="Apple-style-span" style="font-size: x-small;">* After tagging along for one house call I truly believe this as well. It's amazing what they find in the home with respect to medication compliance alone. If you have an elderly family member I recommend calling your local house call doctor to see if their insurance covers house calls. </span></div>eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com2tag:blogger.com,1999:blog-2906216102316790874.post-89537946840079101522010-06-20T13:50:00.000-07:002010-06-20T15:42:30.698-07:00Update Mania!It's been a while I know, but I have good reasons I swear! A lot has happened in 2 months and I'll try to be brief. Skip around to specific sections if you like, I won't be sad.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">This Blog</span><br />
I just updated the look and feel of this blog to be up to snuff with the new blogger templates and designs. I rather like the new interface, although I could choke myself on the abundance of fixed width designs out there. Glad to see Plone still hasn't jumped the shark on liquid design. Oh wait...<br />
<br />
I also went and updated code snippets from old posts with <a href="http://gist.github.com/">gists</a>. I'm really happy with the support and although it's no posterous built-in it's easy enough.<br />
<br />
Lately I've been blogging a lot more which means I've become pretty passionate about divvying up my blogging so content streams are consistent. I would hate for people to have to fiddle through stuff they aren't interested in. As a result, all of my Plone blogging is now on the <a href="http://plonechix.blogspot.com/">PloneChix blog</a>. If that's all you care about then head over there! It's also syndicated to <a href="http://planet.plone.org/">PlanetPlone</a> for your simplified user experience. I also started an unofficial <a href="http://eleddy.posterous.com/">idea blog</a> to help me focus some of the cockameme ideas I've had since I "went solo". It's probably not appropriate for anyone really. This blog will remain my official point of contact for non-Plone tech posts, especially high level ideas, with the occasional personal update.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">San Francisco/Work</span><br />
The move to San Francisco was great and I'm super excited to be here. In short I'm extremely happy with the decision and life is already unfolding some very promising ventures.<br />
<br />
In an surprising turn of events my company received a huge some of investment capital. It's not official yet so I can't explode the details but it's a crazy story nonetheless. This means I won't be spilling beans anytime soon about my departure and despite the funding effort, I have already migrated to a contractor role with the company. The primary focus here will be a Plone 4 migration. After that I'm hoping to hand off the project to those who are happy to work in large system services interfacing - something I loathe entirely. The project has really grown up in the last 3 years, interfaces are solidified and features are stable, so I'm happy to pass the reigns to those that can take it the next level.<br />
<br />
I will be dedicating 50% of my time to that effort at least until the end of the summer. The rest of my time is currently dedicated to exploring other opportunities, mostly in technology, and exploiting a new "tech bohemian" lifestyle. More on that in a later post.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">Accident Report</span><br />
Those that know me well will not be surprised by this at all. 1 week ago I was in a bike crash and am stuck inside for the next 5-6 weeks with 5 fractured ribs and a pneumothorax. I clipped a post on a multi-use trail which included me somehow crushing my ribs on my handlebar. I've probably fallen on my road bike 20 times and mountain bike plenty more but this just happened to be the unlucky one. Of course I clipped the post because I was not paying attention. I was not paying attention because 1) I was geek+climb talking with <a href="http://twitter.com/sudarkoff">@sudarkoff</a> and 2) I was feeling overly comfortable because I was on a "protected path". I usually ride in the road because Bernat claims that bike paths "are just asking for trouble". We used to argue about it but he definitely won this one. Just goes to show that comfort/apathy, no matter what sport you practice, is more dangerous than <s>any</s> most extreme situations.<br />
<br />
And now it's time for consequences. I already did 1 triathlon this year and luckily had put off signing up for 3 more do to being lazy. I am going to bypass the rest of the season to focus on recovering and rebuilding. Although I was running and swimming my fastest ever before the crash, set backs like this are always a great time to rebuild with better technique.<br />
<br />
Climbing will be halted a little longer, since climbing from my left upper body is especially precarious. My trip to Pinnacles has definitely been cancelled and while I most likely won't make the <a href="http://climbingtweetup.pbworks.com/">Colorado Tweetup</a> I'm shooting to be back in full force for the <a href="http://climbingtweetup.pbworks.com/2nd-Annual-JTree-Tweetup">2nd Annual Joshua Tree Tweetup</a>. On a happier note, this injury will force me to do what every climber tries which is focus on feat, feat, feat!<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;">On CT Scans</span><br />
A quick little aside for anyone interested in a medical tidbit. When I was in the hospital I had a few x-rays and an abdominal CT scan. When the scan was done the radiologist said my kidney had spots - noise from a bad machine reading. My attending doctor said it may be blood clots and dosed me with a blood thinner (heparin) for a few days. A specialist finally looked at it and said "we'll just do another one later". When I was about to be discharged, the attending physician said that he didn't think the spots were "worth the risk" and discharged me without a followup CT.<br />
<br />
Of course the specialist called me later that same day and wanted me to still come back for the scan. I had some insurance stuff to work out but then had a thought, what did he mean "worth the risk"? So I did a little research first. Turns out that an abdominal CT scan has the radiation equivalent of <a href="http://docs.google.com/viewer?a=v&q=cache:O5jt7vQ5BP0J:www.sdadefend.com/MINDEX-C/CTScan-M.pdf+ct+scan+abdomen+400+xrays&hl=en&gl=us&pid=bl&srcid=ADGEESjzYHfaxX__0S600ssPVNh4IgkVLhiMolNclDPpeYtCqizs7riaT_QSu7nWHf3dIcU6rr8-3mybJJnrR327_rYtigNnF80k8hk4K_3Ha5TyJsWO1prxitvRvmVmuPRNijYOeYlG&sig=AHIEtbQWadgUIpeyGh2dF-mxM-bGoG2igg">400 x-rays</a>, and the leftover radiation will stay in the system for about 2.7 years. Yikes!<br />
<br />
Would I have turned down the first scan? No way. I absolutely needed it. However, I will be taking the risk and turning down the follow-up. I had no symptoms whatsoever of kidney problems and have already racked up 3 abdominal CTs in my life from a previous injury.<br />
<br />
I am sharing because I was never informed of these risks, and had I not been discharged would have blindly gone in for the second CT scan. So if you took the time to read this blip and you or a loved one comes across a <b>non-urgent</b> decision to do a CT scan, especially abdominal, please research the risks involved. When in doubt, get a second opinion!<br />
<br />
That is all! See you at the next life changing event.eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com2tag:blogger.com,1999:blog-2906216102316790874.post-16273097565907530142010-03-30T16:54:00.000-07:002010-03-30T16:55:10.942-07:00Coming May 2010 to a Bar Near You: There Will Be BeerAfter 3 years of building from the ground up, our company is out of money. There is a small chance that the funds will show up last minute, but after working for almost 3 weeks without pay, I'm not placing any bets on success.<br />
<br />
<div>I'm currently not at liberty to explain how it all went down, but I promise to go into detail next month after things have solidified. It was unlike anything I have ever experienced. No one really blogs about what its like when a company fails - the disintegration of morale, the death of the product, and the denial that leads up to the final stake. There are also of course obligatory lessons learned, technical at times but mostly personal, that I hope to detail over the next couple of months in short posts. Hopefully they will be useful for a young gun thinking to get into the startup world, especially someone else's startup.<br />
<br />
</div><div>In the meanwhile, I've decided to finally move to San Francisco and end a commuting relationship of 2 years. I'm very excited to plug the holes in my personal life that my job has kept me from fully exploring. I am also excited to get be in a city exploding with technical prowess and excitement.<br />
<br />
</div><div>For now, I'm getting my crap together and in a month or so will start to act on what's next. I'm hoping to spend an additional month or two working on some projects I've always wanted to complete (thanks to @yood for the inspiration!). After that I'll probably move into a consulting position or the right full time position should it fall in my lap. More on that later as well once I defrag from all the excitement of the past month.<br />
<br />
</div><div>That being said, my first mission when I get to the bay area is to rally the Plone community that appears to be sleeping soundly there. Be prepared for meetups, sprints, shenanigans and various references to pants. This is your warning ploners... there will be beer.</div>eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com1tag:blogger.com,1999:blog-2906216102316790874.post-55727311353923018842009-11-18T16:17:00.000-08:002009-11-18T16:19:32.497-08:00Knot Pop Quiz<span style="font-size: large;">THE QUESTION</span><br />
what <a href="http://www.flickr.com/photos/38696549@N03/3557165868">knot is this</a>? any idea?<br />
<br />
<span style="font-size: large;">THE ANSWER</span><br />
Bowline. In this form it's sometimes called a 'double bowline'.<br />
<br />
In the old days this knot was used to tie the rope around your waist- no harness. If the leader fell, and the rope didn't break, the result was not pretty- broken ribs were common. When harnesses first came around the bowline, and later the double bowline, was the standard tie in knot. Some people still use it to tie in, it's supposed to be easier to untie after being loaded than a figure eight, but it has sharper bends in it which means it's a slight bit weaker than the figure eight. Any bend in a rope lowers its breaking strength, and the sharper the bend the more the rope is weakened. The figure eight has the least sharp bends of any known knot, making it the 'strongest'. It is also easy to tie and easy to glance at it and verify it is tied correctly- which are the main reasons it is preferred by most climbers today.<br />
<br />
<span style="font-size: small;"><b style="color: #666666;">Note</b><span style="color: #666666;">: This post was ghost written by me for "could have been my first guest blogger but refused" </span><a href="http://nealharder.com/" style="color: #666666;">Neal Harder</a><span style="color: #666666;"> in response to </span><a href="http://twitter.com/sudarkoff/status/5836400206" style="color: #666666;">http://twitter.com/sudarkoff/status/5836400206</a><span style="color: #666666;">. aka I just copied his email response into this form since he's "allergic" to blogging.</span> </span>eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com2tag:blogger.com,1999:blog-2906216102316790874.post-53532087202060115062009-10-28T03:05:00.000-07:002010-06-20T12:29:06.213-07:00Twisted Reactor w/XML-RPC, POST, GETRewriting our Berkeley XMLDB services on Twisted, I decided to implement some couch db type interfaces like responding to post and get requests for DB actions. Oh, and don't forget the already in use xmlrpc interfaces to stay backwards compatible! It was surprisingly simple after staring at the docs for a day or two, so I'm posting a piece of the code in hopes that the example makes it easier for people new to twisted. Below you'll find an example which not only covers the post/get/xmlrpc thing, but also has threadpools, deferreds, xmlrpc kwargs, and a reactor example. There are some pieces missing since the server is actually much more complicated but hopefully you get the idea. Bon appetite!<br />
<script src="http://gist.github.com/446032.js"></script>eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com0tag:blogger.com,1999:blog-2906216102316790874.post-79606256279180318112009-01-08T15:33:00.000-08:002010-06-20T12:34:09.261-07:00Plone LDAP and 450% speed increase rendering page load time"Where I be workin' now we's goin through trubles, perfomance troubles solved by ma jigga... me?"...<br />
<br />
ok - so I can't rap. big deal, neither can you. point is that we have been investigating the curmudgeouness in our plone 2.5.3 custom archetypes based product and came across this gem of a performance fart. our setup is weird I confess and I would be suprised if this actually applies to anyone but nontheless, thar she is.<br />
<br />
we have many different users base dns in active directory that share the same group dns (scalability reasons) that map to zope roles. so we make plenty o' calls to see groups members to list them. turns out that this setup had something weird: our manager dn had permission to list other portals dns members but not to retrieve them. so if our user dn from one portal instance was "OU=AWESOME,DC=WE_ARE" and another was "OU=OK,DC=WE_ARE", they could share a groups DN of "OU=EDITORS_GROUP,DC=WE_ARE". The query to ldap for members of editors group would then return all user it can list, not edit, from both portals since they share this gruoping. Seems harmless enough right?<br />
<br />
WRONG<br />
<br />
(that could not be dramatic enough).<br />
<br />
so for each user that comes back from the groups listing, there is a call to get that user. if that user call fails (i.e. the permission fails) the user is just ommitted from the list. so if those two portals each have 50 users in them, then there are 100 calls to get users from either portal, even though only 50% are accurate. oh, and each call is 1/10th of a second each.<br />
<br />
<script src="http://gist.github.com/446035.js">
</script>eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com0tag:blogger.com,1999:blog-2906216102316790874.post-66583918944715050072008-10-20T19:33:00.000-07:002008-10-20T21:48:00.106-07:00If its not asynchronous yet, make itI am at war. It is a war against apis, query strikes, and unicode bombs. The enemy is Berkeley XMLDB, and I'm tired of losing. <div><br /></div><div>My battle at bunker hill has been using this embedded database in a server environment. XMLDB and its corresponding python bindings are not optimized OR designed for server environments. Because its embedded, it has some very negative server side effects:</div><div><ul><li>if the db segfaults, the server segfaults</li><li>since the python bindings are a swig wrapper, the c libs segfault easily</li><li>if the db hangs, the server hangs</li><li>no persistent connections are a performance hit</li><li>multiple dbs are a management headache</li><li>multi-threaded processes are not well supported out of the box, and servers are multi-threaded</li><li>multi-processes are not supported at all, and can cause mega corruption of the database</li><li>if anything goes wrong with anything, recovery has to be single process single thread, meaning that all connections have to be terminated to bring one db back online</li></ul><div>All these things add up to down time, down time, down time. Down time means I'm losing. It stresses you out to the land of disappearing productivity and forces mistakes. And then there is the ever present fear that one day a recovery will corrupt it all. XMLDB, I'm coming to fix you. You better be ready.</div><div><br /></div><div>Now I need a game plan. First things first, tackle swig and any nasty exceptions that come out of it. Minimize encoding errors, separate interfaces, and wrap, wrap, wrap. Protection is the name of the game, and to ease the blow of attacks I'm gonna need some good armor. With every call to swig there will be a try/except/finally there on the defense.</div><div><br /></div><div>Java weenies seem to have a web friendly XMLDB interface thats filled with interfaces of wrappers of SOAP and jsr*** that is a great idea but just won't work. Adding java to a python architecture is just going to make environment variables clash and maintenance will bring my men down. To counter, I've started playing with <a href="http://twistedmatrix.com/trac/">twisted</a>, as its guaranteed single threaded and can manage its threads to aid recovery. This should help separate the server from the db, a strategy that should have been painfully obvious from the start. It should also maintain an xmldb version of "persistent connections". Finally, a separate server means that if xmldb goes down, it doesn't drag plone into the mud with it. More men on the field means more threads could die, but it also means more threads to fight.</div><div><br /></div><div>Living in a world of synchronous calls has been a dangerous game. Ideally I would like to update things on the spot, but anytime I depend on something being up, it is down. Storing data in a processing queue (such as a fancy xml feeds folder) is not premature optimization, just a smart way to never underestimate the power of the "retry" from transactions of web requests. That's one thing java heads got right and I hope it will be the nuclear bomb in my currently weak arsenal.</div><div><br /></div><div>Onwards and upwards I guess: XMLDB, prepare to behave.</div></div>eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com4tag:blogger.com,1999:blog-2906216102316790874.post-79301907890373155532008-06-13T02:57:00.000-07:002008-06-13T04:24:01.273-07:00My Abstraction OptimizationHere at Anus Health, you kinda get used to doing things multiple, unnecessary times: redoing the work of minions, retring bad data calls, or explaining complicated migration procedures to pointy haired bosses. The worst is writing code - write, rewrite with a better data model, reformat, add a tiny feature, clean - it never ends. With over 15,000 patient records filling over 13GB of data, today is the day where I need to start thinking about performance and rewriting better, more scalable code...<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://eleddy.com/blog/uploaded_images/DSC00350-706227.JPG"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://eleddy.com/blog/uploaded_images/DSC00350-705996.JPG" alt="" border="0" /></a><span style="font-size:130%;">Abstract Out, Then Optimize In</span><br />I tend to build software according to the adage "if it doesn't make sense yet, just build another layer of abstraction". You know what? It works. Put time up front to make really nice abstractions and even the dumbest of colleagues are knockin' out working code like monkeys eat lice. But there is a price for abstraction in the end, and that tends to be performance. Every layer that you added is spinning the disk better than Punjabi MC and eating more RAM than your mom. The classic example of this is my good friend Plone. Amazing to quickly buildout an app, but I'll be damned if after 6 years of development experience, intense caching policies, and 16GB of RAM I still can't get it running much faster than a hobo on a train track.<br /><br />In my last post, I talked a lot of shit about not worrying about scalability. If you're lucky, you get to the point where you actually have to start worrying because good caching and hardware is only gonna take you so far. The interesting thing about this is that after you spend all that time abstracting away from the nitty gritty, you know have optimize back down through the layers to find efficiencies: build things up and then tear them down. This is exactly what twitter is doing. Now that things are huge, start replacing those yummy developer abstractions with good old nasty C. Instead of using an ORM, write your reports direct from MySQL then take it a notch further and read directly from disk. Optimization high five - whipish!<br /><br />The thing that uber sucks about optimizing an abstracted system is the fact that these optimizations are not easy to write. Current interfaces are entagled in kludges deeper than a whales vagina. The little pieces of backwords compatability from your 1034th version of the photo album picture are just barely holding up as it is. What is a developer to do? Have the Java weenies been right all along?!? Stay tuned...<br /><br />Next time on Sincerely, Management:<br /><ul><li>"My Responsibility Response" - Things get whackey at Anus Health when Liz learns that Plone can't do everything, especially reports. Guest starring "IT guy".</li><li>"My Feed Lust" - After a losing battle with IP latency and unreliable 3rd party API responses, Liz shows instantaneous response the door. Not suitable for children under 25.</li><li>"My New XML Fetish" - Liz sends JSON & GET packing after they discover her steamy affair with XML, starting a dangerous journey away from friendly 3rd party developer API land.</li></ul>eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com0tag:blogger.com,1999:blog-2906216102316790874.post-22602256102059836212008-05-19T13:33:00.000-07:002008-05-19T15:08:40.086-07:00Opportunity Knocking: SWF ISO QA Cowboy<span style="color: rgb(0, 153, 0);font-size:85%;" >Note: This post is only reflective of my desire to work with someone who doesn't suck, and not of my employer. I have to say, though, that I have considerable pull so get at me if you want to rock with yours truly every day to make some kick ass software that gets used by real people at a well funded start-up.</span><span style="font-weight: bold;"><br /></span><br />Here I am, lonely, and looking for a mate... my one and only work mate! I know that you are out there, and you can roll with the punches like the best of them. I know that you are un-phased by "emergencies" and have corrupted your own database a time or two only to breathe and recover gracefully (at least the second time). I know you aren't afraid of restarting a service live if timed right and that you truly understand that logs are there for more than just wasting disk cycles. You know when to yell at me for my coding sins and when to give me slack for a 95% pass day.<br /><br />Save me from myself and my kludgey disgressions. Are you out there? <span style="font-weight: bold;"></span><span style="font-weight: bold;"><br /><br />MISSION</span>:<br /><br />Help us get our test on by setting up testing protocols, enforcing test suites, and anything else that makes a sturdier code base and happier customers. We have regression/unit testing in place but are looking for someone to enforce that they get run often as well as wrangle together the rest of the test picture pieces including pre and post deploy testing, bugs, new features, and performance.<br /><br />A strong head and leadership qualities are a must: we are growing fast so don't be surprised if you are expected to voice opinions and yell about the right way to do things now and then. You will be given any tools you need to maintain system integrity and enforce test policy.This is the perfect position for someone who is ready to step it up a notch and help lead a small company to success-ville.<br /><br />For those that are interested and able, this position can easily and quickly turn into a developer position.<br /><br /><span style="font-weight: bold;">SYSTEM</span>:<br /><br />We work primarily with Python and the Plone framework but dabble in many arenas such as COM, XMLRPC, XMLDB, Adobe Livecycle Workflow and Designer, etc... depending on what needs to be glued at the time. You will learn and understand how all these pieces fit together into one beautiful system and are expected to care for each piece like it was written by you.<br /><br /><span style="font-weight: bold;">REQUIREMENTS</span>:<br /><ul><li>BS in Computer Science or must possess portfolio proving proficiency otherwise</li><li>1-2 years experience testing or building web applications, preferably with dynamic languages and kudos if that language is Python</li><li>Ability and excitement to learn new languages/technologies in a web based environment</li><li>Recent grads will be considered if internship experience is close - we will gladly feed and grow you into the position</li><li>Must know when to ask questions and when to ask Google </li><li>Self-sufficient and flexible</li><li>Excellent troubleshooting, analytical, documentation and communication skills</li><li>Must be dependable, have a positive attitude, and be a team player</li></ul>Knowledge of any of the following is a awesome:<br /><ul><li>Experience working with and/or developing in Plone</li><li>Familiarity with Test Driven Development and Agile Methodologies </li><li>History working with XML databases</li><li>Experience with Adobe PDF and/or Livecycle Designer</li></ul><span style="font-weight: bold;">COMPENSATION</span>:<br /><br />Competitive salary based on experience with all the startup stock yummies.<span style="font-weight: bold;"><br /></span>eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com0tag:blogger.com,1999:blog-2906216102316790874.post-59950805108935396082008-05-12T17:20:00.000-07:002008-05-12T18:07:41.801-07:00I Poop on Designing for ScalabilityDear John -<br /><br />Is it OK that I answer your question with a blog post? It seems very web 2.0, and my whole goal in life is to be more web 2.0 than any other web 2.0 weenie out there. Plus, maybe there is a reader out there, and maybe they have a better response.<br /><br />Unfortunately, I've done a bunch of scaling in my short time on this planet (especially working with the notoriously performance agnst <a href="http://plone.org/">Plone</a>) and I have to side with the camp that you should rarely spend time scaling architecture in the beginning. Here are some yummy reasons on why you should wait to pop your scaling cherry:<br /><ul><li>your web app may never take off and you have wasted time scaling when you could have spent time writing a killer feature</li><li>if it does take off, pay someone else to worry about it. If you read anything about scaling twitter, read about how they <a href="http://www.techcrunch.com/2008/04/23/amateur-hour-over-at-twitter/">"fired" Blaine Cook</a> and hired a bunch of scalability experts instead. Zing!<br /></li><li>caching goes a loooong way. I like <a href="http://www.squid-cache.org/">squid</a> myself - it's a sexy beast if a little hard to configure - and I hear <a href="http://varnish.projects.linpro.no/">varnish</a> is pretty top notch too. Hell, httpd has a nice accelerator built in too if you need a quick fix. Let's take a moment and remember WHY caching works so well: it serves up content that an app server like RoR or Django could give two craps about such as javascript, css and images. Have you ever looked at how much time your browser spends loading this stuff? It's a lot, and cache servers know when to expire, refresh, reload http headers, etc. Your cache server may be your users' browsers' best friend.<br /></li><li>you can and should throw more hardware at the problem first. its cheap enough these days and it will buy you the time you need to develop a real scaling solution<br /></li><li>Jared Spool gave a great talk at sxsw about <a href="http://www.uie.com/articles/download_time/">actual performance and perceived performance</a>. the performance of your pages (i.e. load time) is almost always next to perceived performance, the time it takes your user to complete a task. For example, amazon.com takes on average an unthinkable time to load pages but it is commonly perceived as the fastest site out there because of its 1 click functionality to get things done.<br /></li><li>IP latency is a factor. If you are integrating with any external site (who isn't these days?), chances are that you will see more lag time from waiting for responses for that than any kludgey code you can write</li><li>it will rarely clog where you think it will clog so take that pipe dream to the dump and let the bums sleep in it<br /></li></ul>That being said, here are some things you can think about now if you are worried:<br /><ul><li>don't write stupid code. if you notice yourself writing 4 nested loops, think - hey, that could be nasty later on.<br /></li><li>write good db queries and for the love of god don't use your code to filter out the results. in the same respect, don't access database variables more than needed - make a higher level variable and reference that forever. watch out for this in ORMs - they can be very inefficient for scaling even though they make code writing fast. but read bullet 1 above first.<br /></li><li>know your language/tools. if you are using RoR or something that is known to be slow, anticipate it being a problem later and rewriting key parts in a language like C. oh, your language doesn't have C wrappers? that could be a problem ...</li><li>think about concurrency while you are writing for KNOWN expensive operations. Think: does this action rely on another action before going to the next step? For example, we have a process which needs to create an appountment in exchange and then attach 2 files to the resulting appointment. Instead of writing a functional piece of code like so: create appointment (2s) > attach file 1 (60s) > attach file 2(120 s) > report results(2s)) totaling 184sec, think of doing a threaded version: (create appt(2s) > report results(2s) > kickoff concurrent attach threads(120s) ) totaling 124 seconds. Web peeps don't think about concurrency enough. Be different.<br /></li><li>put a round robin queue that diverts from dead parents so you can hot patch stuff live if your code requires restart for changes to take effect (i.e. compiled code). this has saved me a hundred times over and eliminates downtime while still allowing you to respond to heinous bugs.<br /></li></ul>Last but not least, don't forget Knuths famous words of wisdom: "Premature optimization is the root of all evil!!!"<br /><br />This <a href="http://gojko.net/2008/03/03/two-data-streams-for-a-happy-website">data streams crap</a> seems like it was written by an <a href="http://www.joelonsoftware.com/items/2008/05/01.html">architecture astronaut</a>. Yeah right! Who really writes code like that? (hint: no one).<br /><br />Hth,<br /><br />Liz<br /><br />>>><br /><blockquote><span style="font-size:85%;">...<br />So, although I truly want to know how you're doing, I also have a question for ya. It stems from thinking long and hard how to go about building the architecture for my latest startup. I've read interesting posts such as Two data streams for a happy website (http://gojko.net/2008/03/03/two-data-streams-for-a-happy-website/) and Scalability (http://romeda.org/blog/2008/05/scalability.html) from Twitter's Blaine Cook, but it's hard to figure out where to go from here.<br /><br />Basically... how much time do I spend planning how the architecture can scale before I know the metrics. I've read that I shouldn't worry about it until I'm there, while others say to keep 2 separate data streams (one that requires users to be logged in and one that doesn't). I expect to have to tweak the solution if we do reach limits, but the more I know before I start writing code the better.<br /><br />Have you (or friends you know) hit this problem? What advice could you provide?<br /><br />Thanks in advance!<br /><br />Best,<br />John<br /></span></blockquote>>>>eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com4tag:blogger.com,1999:blog-2906216102316790874.post-12277884994127918372008-04-24T09:58:00.000-07:002008-04-24T14:36:24.237-07:00Press or say 3 if you're being robbed by gunpointDear 911 Emergency System Manager Dude,<br /><br />There is a man on the intersection of the 163 North and the 8 East, lying on the ground, with blood coming out of his head. There are 5 cars involved, maybe 6. It's 9:30 am, and there is a lot of traffic headed directly at the accident. Even though I know its probably already been reported, I pick up my phone to report the crash and make sure bloody guy gets the ambulance he needs. This is the phone call I expected to make:<br /><br />Me: 9-1-1<br />911: This is 911 please explain your emergency<br />Me: There was an accident on the 163 and the 8 and there is a man lying on the ground with blood everywhere that probably needs an ambulance<br />911: We'll make sure to send someone out there<br />Me: Thanks!<br /><br />However, the emergency reporting system had "upgraded" since the last time I used it. Below is the phone call that actually happened. WARNING: extreme ellipses may follow.<br /><br />Me: 9-1-1<br /><span style="font-style: italic;">busy signal</span><br />Me: ...huh...<br />Me: 9-1-1<br /><span style="font-style: italic;">busy signal</span><br />Me: 9-1-1<br /><span style="font-style: italic;">phone rings</span><br />Phone: Welcome to the California Highway Patrol<br />Me: Hi I'd like to report...<br />911: ... If you would like to report an emergency, please press or say 1 now<br /><span style="font-style: italic;">Me listens to the menu</span><br />911: <something><br />Me: ...<br />911: If you would like to report an emergency, please press or say 1 now<br />Me: ... huh?<br /><span style="font-style: italic;">911</span> <span style="font-style: italic;">hangs up</span><br /><br />Terrible emergency system design just happened, and it may be killing people. From the moment I got the first busy signal (is it 1982 again?), this shiny new 911 reporting system/workflow/call-taker/whatever made it hard for me to complete a critical task and gave me motivation to write about the lessons learned from this short dialog.<br /><br />A key concept in designing obviousness is that all choices should be as easy as possible. I had already decided that this was an emergency by dialing 911, and yet they forced me to rethink my choice verbally or by touch tone. You know 911, you're right, this isn't an emergency - I was robbed by gunpoint and killed by the time I figured out what the hell was going on with your system. Note to everyone who makes things: reducing redundant choices is the key to accessibility by end users and marks the efficiency of a system.<br /><br />Deciding to use an automated system for a critical human-centric task such as 911 is a huge mistake. People (read:I) hate automated telephone systems and even if they have come a long way since first inception they are notorious for long waits, incorrect routing, and frustrated end users. Perhaps they actually <span style="font-style: italic;">want</span> to discourage people from calling 911. In my case, congratulations 911, you have succeeded.<br /><br />After deciding to go with the automated answering system, someone made a decision that talk to an operator was not an option in the main menu, let alone the <span style="font-weight: bold;">default</span> choice. Systems that ignore the usage patterns in which all of its users exist will suffer if not die before the second server is even plugged in. Even if the new system is better in every which way, a good system has no traction if people can't use it based on some piece of previous knowledge. Every automated system has a skip to operator option - where is yours 911? I can't find Ctl + Alt + Del on my phone...<br /><br />So whomever made the decision at 911 headquarters to switch from an easy to use, simple emergency system to an automated, confusing pile of crap, congratulations on your un-success! You're fired.<br /><br />Now can I have my old 911 back?<br /><br />Sincerely,<br />Managementeleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com0tag:blogger.com,1999:blog-2906216102316790874.post-21493969289631273732008-04-11T10:56:00.000-07:002008-04-11T12:19:14.887-07:00No Frustration Setup PolicyWhile many designers spend countless hours thinking about the design and usability of a products functionality, it seems that many neglect the experience of new user setup/assembly. Here is my tale...<br /><div style="text-align: justify;"><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://media.rei.com/media/o/1454104.jpg"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 243px; height: 243px;" src="http://media.rei.com/media/o/1454104.jpg" alt="" border="0" /></a>I recently purchased and camped with the <a href="http://www.rei.com/product/761895?cm_re=shop*sh*qtdomet3">T3 Quarter Dome tent by REI</a> and it was the best new setup experience I have had with a product in many, many years. So good, in fact, that I decided to dedicate this post to it. I'm sure anyone who has camped has felt the frustration of arriving late to a site and trying to assemble a tent in the dark for the first time, fumbling with the user manual to find out which posts attach to which side of the tent, why something seems to be unnecessarily tight or loose, etc... Arg! It seems that the designers of the T3 have also felt this pain (dare I say listened to their users?) and provided the following anti-frustration features that are simple and just knocked my socks off:<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://media.rei.com/media/o/1454104.jpg"></a><ul><li>Connected support "rods": support pieces are tied together with bungee cords in the middle, meaning that it almost instantaneously assembles in the right way as soon as you pull it out of the bag, and also means that you never lose one</li><li>Color coded assembly: the top of the tent has lines in two colors, orange and silver, striping across the top that correspond to the orange and silver colored rods. Since the rods almost assemble themselves, you can see immediately how they lay across the top with respect to the tent. Color coded tags show that orange rod starts and ends in one stripe and the silver rod starts and ends in another. Dare I say idiot proof? I dare!</li><li>Two doors: the flyaway (as well as the tent) has a door on both sides, meaning that you don't have to decide and reducing the amount of times you say "oh wait, it goes the other way"</li></ul>I could go on far too long about the little things that make this tent *fun* to assemble but I think I can go right to the point: <span style="font-weight: bold;">the best user manual is the product itself</span>. Smart use of color to lead the user and simple tricks to prevent "oh wait.." moments can take a user experience from "meh" to "wow" even if the final product is the same.<br /><br />As a counterexample, let me describe the most frustrating setup I've had in many years, which just so happened to occur the week before the best one. I purchased some Speedplay clip in pedals for my road bike and attempted to mount them on my cleats. Here is a sampling of why it took two days to assemble correctly:<br /><ul><li><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://eleddy.com/blog/uploaded_images/shims-763052.jpg"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 191px; height: 271px;" src="http://eleddy.com/blog/uploaded_images/shims-763035.jpg" alt="" border="0" /></a>Bad print: the paper was neon orange and everything is written in 8pt font with bold and underlines exploding on the page to the point of complete ineffectiveness</li><li>Incomplete instructions: additional instructions and warnings were littered in the box like an afterthought, the most important of which accidentally drifted under the table only to be discovered after the problem was solved. I know its cheaper, but just reprint them!<br /></li><li>Color: the only color coding turned out to be things that were irrelevant to assembly as well as screws that were only 1mm difference where almost unidentifiable and shims for different shoes were all the same gray with the label nicely etched in (you guessed it) gray were the most annoying<br /></li><li>Language: assembling these shoes I said "what does that MEAN?!?" more times than I care to share. This instruction sheet definitely needed a definition list<br /></li></ul>After 2 frustrating days of wondering if it was my poor instruction reading, new pedal break in, or the pedals just not living up to the expectation set, I finally got things working right. With both products, after things were put together correctly, the end products were awesome and I am happy with my purchase decisions. However, if someone asks me about my pedals I'll recommend with a disclaimer: "...but it was a bear to assemble so watch out". You probably don't need to ask me what I think about the tent because if you know me, you already know.<br /><br />So from here on out, a new No Frustration policy for getting started with a product made by LizCo is active. Any questions can be directed to your closest level of management and there is a reward for snitching on any product produced caught violating the new policy.<br /><br />Now if I could just produce something...<br /><br /></div>Sincerely,<br />Managementeleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com0tag:blogger.com,1999:blog-2906216102316790874.post-10176489927678381602008-04-04T10:34:00.000-07:002008-04-20T22:19:18.741-07:00Blog PolicyDear Loyal Followers,<br /><br />I know you have been dying to know - what the hell is up with Liz's blog? I can answer that in exactly 3 lines:<br /><br />1. I had a Plone blog hosted here but now its not<br />2. I never blogged that much in the 1st place<br />3. Textdrive got bought by Joyent and moved from linux to unix servers (yay), asking me to migrate my blog database (boo) and for the love of money I am just too lazy to migrate the old blog so I'm using a hosted site (blogger) that publishes to my awesome URL (<a href="http://eleddy.com/">eleddy.com</a>) to continue to provide you with quality not-blogging. Run on sentences are a new feature that you can come to expect from me this time around...<br /><br />For your convenience, you will not have to update any urls or rss feeds that you never subscribed in the first place. However, to pay for this feature I had to cut some corners so humor is no longer free.<br /><br />To those looking for the old Plone blog, since most of the content is on <a href="http://plonewars.com/">PloneWars.com</a> I will not be republishing here unless someone asks politely. New content on Plone will continue to emerge but old content will remain hidden in the Google cache.<br /><br />I hope you will find these changes amenable to your situation - please direct any requests and/or complaints to human resources aka me.<br /><br />Sincerely,<br />Managementeleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com1tag:blogger.com,1999:blog-2906216102316790874.post-75645246468841435732008-04-04T10:13:00.001-07:002008-04-20T22:20:49.944-07:003 Click Bug Reporting PolicyDear Companies that make web software,<br /><br />As a developer, I know how important it is to get bugs from your users out in "the field", especially all you beta web n.0 site. So, when I come across bugs, I will do my best to let you know what happened in a clear and concise way. However, if I can't find your bug reporting link in 3 clicks, your loss.<br /><br />For example, I was on YouTube today looking for a preview of the "<a href="http://youtube.com/results?search_query=short+circuit+remake&search_type=">Short Circuit Remake</a>" and when I searched, the title bar says there are 4 results but only 2 were displayed. Hmmm.... that's odd... I should report that. 4 clicks, 2 Help Center searches, and no email address later I gave up. Sorry GooTube, you're outta here!<br /><br />Why 3 clicks you say? In reality it should be 1: scroll to the bottom of the page and click "Report a Bug". But I'm feeling generous today on the day I make this new policy so congratulations, you have me for 3 clicks.<br /><br />Sincerely,<br /><br />Management<br /><br /><div><br /><span class="Apple-style-span" style="font-weight: bold;">UPDATE</span>: southwest.com admits they have no email to contact them with - you have to mail in your bug reports, along with any requests or talk to their service representative. Yeah right!<br /></div>eleddyhttp://www.blogger.com/profile/12829844320869028742noreply@blogger.com1