My Secret Life as a Spaghetti Coder
home | about | contact | privacy statement
I recently made a proof-of-concept to get MS Word to edit documents in a Rails app and save them back to the server, using Devise for authentication. It wasn't straightforward, so I thought I'd mention the steps I took to get it done.

I used Rails 3.2.12 with rack_dav providing the WebDAV functionality. There's also dav4rack which was based on rack_dav, and adds a few features.

I started with rack_dav, and had all of the kinks worked out except for the authentication, when I noticed dav4rack included authentication. So I switched to dav4rack, but I had some trouble with it, so I switched back to rack_dav because I feared I'd get into another day-or-two-long yak shaving session.

You might check it out though, and see if it works just as well.

Anyway, here's the basis of what I did.

1. Add the gem to my Gemfile (and run bundle install):

gem 'rack_dav'

2. Mount it in my routes.rb, wrapped with basic authentication:

    webdav = RackDAV::Handler.new(:root => 'private/docs/', :resource_class => LockableFileResource)
    webdav_with_auth = Rack::Auth::Basic.new(webdav) do |username, password|
      user = User.find_for_authentication(:email => username)
      user && user.valid_password?(password)
    end    
    mount webdav_with_auth, at: "/webdav_docs"

3. Create my lockable file resource, which doesn't really do any locking (since this was just a PoC), so you probably want to fix that: More...

Hey! Why don't you make your life easier and subscribe to the full post or short blurb RSS feed? I'm so confident you'll love my smelly pasta plate wisdom that I'm offering a no-strings-attached, lifetime money back guarantee!



Someone from our last houston.rb meetup asked me about contributing to open source software, so I wrote an email that talks about the little things I do. I thought others might find it helpful, so I'm also posting the email here. It is below:

It occurred to me I totally ignored your question about open source, so apologies for that, and here I go attempting to rectify it.

Here's basically what I do: More...


I wanted to turn an HTML <select> element into an autocomplete. I also wanted to match on more than one attribute. So, I made jquery.autocomplete_from_select.js. Thoughts?


Last week at the Houston Ruby User Group I made a presentation called "The Website's Slow" Tips and Tools for Identifying Performance Bottlenecks.

Image of the first slide in the presentation

That link is to the slides and notes on each slide mentioning a little about what I said.

Basically I went through a couple of different classes of performance issues you're likely to see on the server side of things, what tools you might use to make finding the issue easier, how you can interpret some of the data, and even a suggestion here or there about what to do to resolve common issues I've seen.

Let me know what you think! (Or, if you have any questions, feel free to ask!)


A greedy algorithm is an algorithm that follows the problem solving heuristic of making the locally optimal choice at each stage with the hope of finding a global optimum. In many problems, a greedy strategy does not in general produce an optimal solution, but nonetheless a greedy heuristic may yield locally optimal solutions that approximate a global optimal solution in a reasonable time.
What does a greedy algorithm look like?
Images from Wikipedia illustrate the concept well. In the first one, we begin our search of the space for a maximum at point A. If we're greedy, the next highest point takes us along a path that maximizes at point (lower case) m. However, the optimal solution is at point (upper case) M.

Illustration of greedy search along a plane

If you're greedily searching (again, for a maximum) in three-dimensional space, and start in a poor position (like near the left in the image below), you'll never make it off the shorter hill onto the taller one: More...


Your boss gave you three weeks to work on a project, along with his expectations about what should be done during that time. You started the job a week before this assignment, and now is your chance to prove you're not incompetent.

You're a busy programmer, and you know it will only take a couple of days to finish anyway, so you put it on the back-burner for a couple of weeks.

Today is the day before you're supposed to present your work. You've spent the last three days dealing with technical problems related to the project. There's no time to ask anyone for help and expect a reply.

Tonight is going to be hell night.



And you still won't get it done.

What can you do to recover? Embrace failure. Here's how I recently constructed (an anonymized) email along those lines:
  1. Take responsibility. Don't put the blame on things that are out of your control. It's a poor excuse, it sounds lame, and it affords you no respect. Instead, take responsibility, even if it's not totally your fault. If you can't think of an honest way to blame yourself, I'd go so far as to make something up.
    I've been having some technical troubles getting the support application to work with the project.

    To compound that problem, instead of starting immediately and spreading my work across several days, I combined all my work this week into the last three days, so when I ran into the technical problems, I had very little time to react.

    After trying to make the support application run on various platforms, I finally asked a teammate about it, where I learned that I needed to use a specific computer, where I did not have access.

    As such, I don't think I can meet your expectations about how much of the project should be done by tomorrow.
  2. State how you expect to avoid the mistake in the future. Admitting your mistake is not good enough. You need to explain what you learned from the experience, and how that lesson will keep you from making a similar mistake in the future.
    I just wanted to say that I take responsibility for this mistake and in the future, I will start sooner, which will give me an opportunity to receive the feedback I need when problems arise. I've learned that I cannot act as a one man team and I by starting sooner I can utilize my teammates' expertise.
  3. Explain your plan to rectify the situation. If you don't have a plan for fixing your mistake, you'll leave the affected people wondering when they can expect progress, or if they can trust you to make progress at all. Be specific with what you intend to do and when you will have it done, and any help you'll need.
    I already sent an email request to technical support requesting access to the specific computer, and await a response.

    In the mean time, here's how I expect to fix my mistake:

    a) I need to run the support program on data I already have. It will analyze the data and return it in a format I can use in the next process. I can have this completed as soon as I have access to the machine, plus the time it takes to run.

    b) I need to learn how to assemble another source of data from its parts. I have an article in-hand that explains the process and I am told we have another support program that will be available next week. I do have the option to write my own "quick and dirty" assembler, and I will look into that, but I do not yet know the scope.

    c) I need to use another one of our tools on the two sets of data to get be able to analyze them. Assuming I am mostly over the technical problems, I wouldn't expect this to cause any more significant delay.

    d) Finally, I'm unsure of how to finish the last part of the project (which is not expected for this release). If possible, I'd like to get feedback on how to proceed at the next meeting with our group.
After that, close the email with a reiteration that it was your fault, you learned from it, you won't let it happen again, and that it will be resolved soon.

Since I rarely make mistakes, I'm certainly no expert at how to handle them. Therefore, I pose the question to you all, the experts: How would you handle big mistakes? What strategies have worked (or failed) for you in the past?


Several days ago I wrote about common excuses people use for commenting code and things you can do to get rid of them. I took the stance that rarely is there something so complex that it really requires comments.

In other words, much of the time, comments are crutches for understanding bad code.

To show a counter-example where comments were needed, Peter Farrell posted a snippet of code that was hard to understand:

<cfloop condition="patArr[patIdxEnd] NEQ '*' AND strIdxStart LTE strIdxEnd">
  <cfset ch = patArr[patIdxEnd] />
  <cfif ch NEQ '?'>
    <cfif ch NEQ strArr[strIdxEnd]>
      <cfreturn false />
    </cfif>
  </cfif>
  <cfset patIdxEnd = patIdxEnd - 1 />
  <cfset strIdxEnd = strIdxEnd - 1 />
</cfloop>

Indeed, that code is hard to understand, and comments would clear it up. And I'm not trying to pick on Peter (the code is certainly not something I'd be unlikely to write), but there are other ways to clear up the intent, which the clues of str, pat, * and ? indicate may have something to do with regular expressions. (I'll ignore the question of re-implementing the wheel for now.)

For example, even though pat, str, idx, ch, and arr are often programmer shorthand for pattern, string, index, character, and array respectively, I'd probably spell them out. In particular, str and array are often used to indicate data types, and for this example, the data type is not of secondary importance. Instead, because of the primary importance of the data type, I'd opt to spell them out.

Another way to increase the clarity of the code is to wrap this code in an appropriately named function. It appears as if it was extracted from one as there is a return statement, so including a descriptive function name is not unreasonable, and would do wonders for understandability.

But the most important ways in which the code could be improved have to do with the magic strings and boolean expressions. We might ask several questions (and I did, in a follow-up comment to Peter's):
  1. Why are we stopping when patArr[patIdxEnd] EQ '*' OR strIdxStart GT strIdxEnd?
  2. Why are we returning false when ch=="?" and ch!=strArr[strIdxEnd]?
  3. What is the significance of * and ?
In regular expression syntax, a subexpression followed by * tells the engine to find zero or more occurrences of the subexpression. So, we might put it in a variable named zeroOrMore, and set currentPatternToken = patArr[patIdxEnd]. We might also set outOfBounds = strIdxStart GT strIdxEnd, which would mean we continue looping when currentPatternToken NEQ zeroOrMore AND NOT outOfBounds.

Similarly, you could name '?' by putting it in a variable that explains its significance.

And finally, it would be helpful to further condense the continue/stop conditions into variable names descriptive of their purpose.

In the end, regular expression engines may indeed be one of those few applications that are complex enough to warrant using comments to explain what's going on. But if I was already aware of what this piece of code's intent was, I could also have easily cleared it up using the code itself. Of course it is near impossible to do after the fact, but I think I've shown how it might be done if one had that knowledge before-hand.

What do you think?



Google
Web CodeOdor.com

Me
Picture of me

Topics
.NET (19)
AI/Machine Learning (14)
Answers To 100 Interview Questions (10)
Bioinformatics (2)
Business (1)
C and C++ (6)
cfrails (22)
ColdFusion (78)
Customer Relations (15)
Databases (3)
DRY (18)
DSLs (11)
Future Tech (5)
Games (5)
Groovy/Grails (8)
Hardware (1)
IDEs (9)
Java (38)
JavaScript (4)
Linux (2)
Lisp (1)
Mac OS (4)
Management (15)
MediaServerX (1)
Miscellany (74)
OOAD (37)
Productivity (10)
Programming (168)
Programming Quotables (9)
Rails (31)
Ruby (65)
Save Your Job (58)
scriptaGulous (4)
Software Development Process (23)
TDD (41)
TDDing xorblog (6)
Tools (5)
Web Development (7)
Windows (1)
With (1)
YAGNI (10)

Resources
Agile Manifesto & Principles
Principles Of OOD
ColdFusion
CFUnit
Ruby
Ruby on Rails
JUnit



RSS 2.0: Full Post | Short Blurb
Subscribe by email:

Delivered by FeedBurner