Entries Tagged as Best Practices
Once and for all, I have the answer! I've long known and exercised my belief that tabs are (far, far) superior to spaces, but only recently have I gained enlightenment as to exactly why they are superior.
Spaces are "hard coded", while Tabs are "dynamic".
What does that mean, exactly? Every IDE worth a damn allows you to adjust the number of spaces that a tab appears to take up. This is commonly referred to as "tab size" or "tab width". If your team agrees (begrudgingly?) to use spaces, then everyone has the exact same view of the code.
The problem is that people's preferences are different. I might like to use 3 space indents so that things don't start flying off the right side of the screen after just a few levels of nesting, whereas you might like 5+ spaces, to really draw attention to where things nest. There's nothing wrong with either preference. And the beautiful thing is, using Tabs and letting everyone set their own tab width (because one person's tab width has no affect on anyone else's view), everyone gets to see what they want to see.
So there you have it. Tabs win. You're welcome.
Posted in
Best Practices |
Meta
| 5 Responses
November 01 2011
Something I spend a fair amount of time thinking about is what's on the horizon. What sorts of things should my team and I be learning and implementing to make ourselves better developers and a better team, as a whole?
Part of that involves knowing what we already do, and in some cases, do pretty well.
- We have a pretty well defined code-review process and we try to integrate as much feedback from them as possible.
- We are getting better at creating automated tests to make long term application maintenance easier.
- Some of our applications have ANT scripts that make producing Production builds (combined, minified JS + CSS, etc) easier
- We're using Distributed Version Control (git) like a champ, now!
- We pair program, when possible. (It can be difficult to find significant chunks of matching free-time on a small team.)
- We're starting to expose some of our reusable code as REST API's so we don't have to waste time copying and re-integrating them into every application
So knowing what we do well, what are the logical next steps? What should we learn and do to continue growing and taking those next steps? Here are some ideas and my thoughts on each. These are just some things I came up with off the top of my head. What else do you think could be useful?
Chef
Our colleague Lew G has written at some length about his experience learning and using Chef. It sounds wonderful! It sounds ideal! It sounds like it could be kind of... hard.
For one, our group has only one server that we manage currently, and it runs on Windows. The rumor mill says that the Chef support for windows is not nearly as good as it is for unix/linux. Of course, this is third- or fourth-hand information, and subjective at that; so it bears some investigation.
You may be able to find people who would argue against automated server configuration like this, but I doubt any of them will be from our team. Being small means that we have to think about our agility and plan ahead for the worst case scenarios or continually find ourselves dealing with the fall out from the previous week's issues. Having one or two people spending two or three days recovering from a total server loss would be catastrophic to our team productivity. Learning Chef and writing/testing scripts ("recipes", right?) to rebuild a server quickly and at a moments notice would definitely go a long way in our personal DR plan.
Jenkins
Continuous integration is the holy grail of automated testing, and with Jenkins now so available and approachable, it's never been easier. How nice would it be to make a commit to source control, and then a few minutes later get an IM letting you know whether or not the tests are passing? Pretty darn nice! ... And just the tip of the iceberg, of course.
Document-based data stores / NoSQL
I recently did a one-day workshop for Hadoop and learned a lot about it and its sibling nosql/document databases. The biggest takeaway for me and our team was something the trainer said. I'm paraphrasing from memory but he said something like, "If you're not working with 1TB of data or more, NoSQL is not for you." I don't think the Learning Lab has 1TB of data from all of our applications combined (maybe not even breaking into double-digit gigabytes), so it's not really an obvious win for us.
That doesn't mean there's no place for NoSQL in the Learning Lab, though. Suppose we need to write an application that will need to support 10,000 concurrent users for a short period of time. Given a Chef script, it could be pretty simple to spin up a few dozen Cassandra/Couchdb/etc nodes to scale as wide as needed, and adjust on the fly according to performance. I imagine scaling a system like this would be much more manageable than trying to get a single machine powerful enough to run MS SQL at the same scale on a temporary basis (Not to mention the licensing costs, since MS SQL is licensed based on the resources it has available!). So while we probably won't dive into this topic right away, we should keep it on our periphery.
LESS CSS
CSS is a very powerful, and when used well, terse way to style html documents. But it can be a pain in the rear to use. Over time stylesheets tend to grow to unmanageable size, and it's incredibly difficult to write them DRYly. Enter LESS CSS. To quote a friend of mine, LESS "makes CSS think like programmers do." You can create and use variables and functions, include files, and much more... and it all compiles (almost instantly, from what I hear) to the native CSS we know and ... erm... love (?) today.
This is another post originally written for my team's blog
Posted in
Best Practices |
Learning
| 2 Responses
September 16 2011
I originally posted this on my team's blog, but once again I'm cross-posting it here as well due to its relevance.
I bet that if you ask programming job applicants what their thoughts on automated testing are, the vast majority will say it's a good thing. Yet, like most of the development shops I've worked for over the years, we aren't always afforded the time to write automated tests. Most of the time, we only have ourselves to blame for this: Who creates the project estimate? Who creates the project plan? We do! So we should plan additional time for them... But I will admit that while I personally have written tests for some of my personal and professional projects, they are few enough and far enough between that testing still isn't quite second nature for me; and I probably spend more time writing my tests and mocks than someone who does 100% Test Driven Development.
I know you already believe in automated testing, but I'll continue just in case there's a non-believer reading over your shoulder. TDD slows you down (less when you're an experienced, disciplined TDD'er)... there's no doubt. Writing tests is almost as counter-productive for the initial development period of the application as checking your Facebook page, your Twitter feed, and your G+ stream, before taking a long lunch. Even for that parenthetical TDD Ninja. Where TDD saves you mountains of time is in refactoring.
Refactoring
A significant number of refactorings are fairly simple; limited to one or two files and maybe a couple of dozen lines of code changed. But we've all been here: What about that change that you were expecting dreading the client would request, that takes you two days to complete, and touches dozens of files, and hundreds of lines of code? Sure... you know that what you just spent two days agonizing over works pretty well. But did you break anything?
If you have tests, you just push a button, go get some coffee, and come back to find out what, if anything broke. Effectively it costs you zero time, and you can either publish your flawless refactored code or, perhaps a touch more realistically, get to work fixing the bits that you broke.
Without tests? Best case? You spend a few hours poking around, trying to remember all of the things this app does, seeing if it still does them correctly. If you're lucky, it's only been a year since you last thought about this application. You might find some or most of the bugs you've introduced, but the more code you've changed, the more likely it is you'll miss something.
Case in Point
I just finished writing some mocks that the tests for the authentication and registration module use to verify different response scenarios from the remote authentication and permissions API without actually interacting with the remote API. I realized pretty early in the process of coding the module that it would need to use a façade to make the mocking easier, and this was something we had done with another module that used the same remote API -- but unfortunately we were a little short-sighted and that façade was specific to the module that was using it, not the API it was wrapping. Since my new functionality was somewhat complex, I decided to take on the short-term technical debt of simply creating another module-specific façade, and get it working, so that my coworkers weren't waiting on me for too long. After finishing the functionality and the tests passed, I knew had two jobs to tackle:
- Add in the mock so that the remote API was not a dependency for the tests
- Refactor the new façade I created for my module and the other module-specific façade into one API-wrapper façade
The change spanned 8 files and affected hundreds of lines of code. And when I was done, luckily, only one test was now failing. Instead of turning more of my hair gray and wondering how much code is broken that I don't know about, I can say with near certainty none is. I love TDD.
My new Rule of Thumb
Of course TDD (and automated testing in general) is a great thing to have for your average project; I don't think anyone would argue that point. But a lesson I've learned this month is that automated testing is particularly necessary when writing an application that uses ORM. Time and time again I've made what seems to be a tiny, innocuous change to my ORM configuration, and all of a sudden I've got 6, or 8, or 11 failing tests. Entirely my fault, of course; but the point is that what seems like a trivial change to ORM configuration can have nuanced effects on lots of existing code.
So I've got a new rule of thumb: Don't write an ORM-backed application without automated tests.
Posted in
Best Practices |
Hibernate
| No Responses Yet
August 22 2011
I regularly use the CFHtmlHead tag to add things like CSS to the header section of a page from various places. It's a very handy tool.
For a long time now, I've wanted a CFHtmlFoot tag, for putting JavaScript at the end of the page, which has been a known best practice for what seems like a millennia. Tired of waiting, I created my own. Here's the custom tag (save it as "htmlfoot.cfm" in your custom tags folder):
<cfif thisTag.executionmode eq "end">
<cfparam name="request._htmlFoot" default="#arrayNew(1)#" />
<cfif structKeyExists(attributes, "output") and attributes.output>
<cfloop array="#request._htmlFoot#" index="i">
<cfoutput>#i#</cfoutput>
</cfloop>
<cfelse>
<cfset arrayAppend(request._htmlFoot, thisTag.generatedContent) />
<cfset thisTag.generatedContent = "">
</cfif>
</cfif>
And here's how you use it. First, let's say you need to add jQuery to the end of your page.
<cf_htmlfoot>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</cf_htmlfoot>
This adds the content between the <cf_htmlfoot></cf_htmlfoot> tags to an array in the request scope. Next, we need to output the contents of that array. This works best when you are using a framework or a custom tag to wrap your content in a consistent layout, because then you only need to put it in one (or a few) places. To output the saved bits of content, add this line:
<cf_htmlfoot output="true" />
Posted in
Best Practices |
ColdFusion
| 1 Response
January 07 2011