When I did all the programming for the original version of Basecamp back in 2003, we ended up shipping with just about 2,000 lines of code. A lot has happened in those eight years and we’ve acquired a more delicate taste of just how beautiful we want the basics executed.
This means significantly more code. Here are the stats from running “rake stats” on the Rails project:
On top of that we have just over 5,000 lines of CoffeeScript — almost as much as Ruby! This CoffeeScript compiles to about twice the lines of JavaScript.
Basecamp Next is running Rails 3.2-stable and we’ve got a good splash of client-side MVC in the few areas where that makes sense through Backbone.js and various tailor-made setups.
Got any questions about our stack or code base? Post them in the comments and we’ll fill you in.
Jason Langenauer
on 30 Jan 12Do you still use Test::Unit for the test suite, or have you moved to RSpec?
DHH
on 30 Jan 12Jason, we’re TestUnit all the way! It’s no secret that we aren’t the biggest fans of RSpec at 37signals. The most important thing is to be testing, but…
Damien
on 30 Jan 120.8 as the code/test ratio ? That’s pretty low :(
RIchard McIntyre
on 30 Jan 12It is interesting you only have 8 helper classes to your 51 controllers but Rails generator still creates a helper class automatically even though you are more likely to not need it.
Bernhard
on 30 Jan 12Are all your views done with CoffeeScript?
DHH
on 30 Jan 12Bernhard, no, the vast majority of all our views are done using ERB and generated server side. We have pockets of client-side MVC for when that makes sense, like our new Calendar and a few other UI elements.
Ryan Fitzgerald
on 30 Jan 12What do you use for clientside templating and do you expose any rails helpers in javascript, such as url_for or image_tag?
Mal Curtis
on 30 Jan 12@Richard
There may only be 8 helper classes but I imagine heavy refactoring helped, as there are still 188 methods to the 300 controller methods.
Henrik Hodne
on 30 Jan 12@Richard: The generators usually generate a lot more code than necessary, which is why (I think) not too many use them after working with Rails for a while. I prefer to create everything myself, that way I have more control.
Nick
on 30 Jan 12Damien: Agreed! In general though that’s a terrible metric…no one metric can give a good general picture of the level of testing that an app has. (Ok, when maybe ls test/ is empty, that’s bad)
However, it’s a good indicator that we need to do more, which I won’t disagree with. :)
DHH
on 30 Jan 12Ryan, we use Eco for our client-side templates, but we only have 24 of those versus hundreds of regular ERB templates. Half the client-side templates relate to our new calendar.
Lee
on 30 Jan 12You’ve been somewhat of a critic of client-side MVC in the past. What changed? Are we now looking at the possibility of inclusion of a client-side MVC framework in future versions of rails? Or are you sticking to your guns, and leaving that up to developers to setup?
Jake
on 30 Jan 12107 lines of code per method on average per unit test ? vs 4 lines of code per method.. or am I reading that wrong?
Are you using Jasmine to test all the CoffeeScript ?
Lakshman
on 30 Jan 12What does your backend persistence comprise of?
Postgres, MySQL, MongoDB, Redis?
And how do you plan to distribute that Terabyte of RAM? Do you also use SSDs?
Richard McIntyre
on 30 Jan 12@Henrik Yes exactly my point that generators create more code and files than is often used. Although I don’t mind creating the files myself, I thought part of the point of the generator was to streamline the agile process somewhat.
It is interesting to see people not using this. BTW do you use the generator to create your migrations or not?
DHH
on 30 Jan 12Lee, I still don’t like client-side MVC from a developer’s standpoint, which is why - comparably speaking - there’s only a tiny amount of it in Basecamp Next. But there are indeed places where it makes a lot of sense, such as a calendar, for example.
But no, I don’t see us including any client-side MVC framework in Rails.
MattO
on 30 Jan 12Did the original code ship with any test code? If not, the almost 7,000 lines of test code makes comparison not quite consistent.
I’m not saying test code isn’t important, but following the assumption that more lines of code = more complexity. Comparing 6962(functional code) to 2000 is more accurate than 14870 to 2000. A ratio of 3.4 instead of 7.4.
How do the numbers of classes and methods stack up to those in original code base?
DHH
on 30 Jan 12Jake, wups. Those stats are wrong. It must be because we’re using the test ”” do/end style that it’s not delineating between methods in the tests.
DHH
on 30 Jan 12Lakshman, we use MySQL 5.5 as our primary data store. We use Redis for a few thing, most importantly Resque. We use Memcached for all our caching needs.
The MySQL database is running on top of SSDs. The Memcached servers are the ones gobbling up that terabyte of caching RAM. Redis doesn’t need much.
Jim Ryan
on 30 Jan 12As Nick said, the code to test ratio isn’t a very good metric, as it says pretty little about the effectiveness of your test suite. Regardless, the 1:0.8 ratio struck me as pretty low compared to my own projects. A project I’m working on right now has a ratio of 1:3.1, and one we finished not too long ago was 1:2.7. Both were using RSpec. Do you think that somehow speaks to the lines of code it takes to write the same test in RSpec versus TestUnit? Or do you guys just write REALLY efficient tests?
DHH
on 30 Jan 12Matt, the original Basecamp also had a 1:0.8 testing ratio, actually. I wasn’t counting the testing KLOCs in either quotes.
DHH
on 30 Jan 12Jim, a) I do think RSpec is verbose but b) I think many people test too many things without thinking about whether it’s worth testing. I’ve seen lots of people test features of Rails, like their validations. If you’re testing framework features in your app code, you’re doing it wrong.
Alexander Tipugin
on 30 Jan 12Do you use Inherited Resources or similar stuff to keep controllers smaller?
Jim Ryan
on 30 Jan 12DHH, interesting. I’m constantly torn on what to test, I still feel like I’m often doing it wrong. I do test that validation rules exist, but not that they work. Would you say that’s appropriate?
Could you recommend any resources that discuss the testing pattern that you use at 37signals? I’d be very interested in reading up on how you guys work.
Nick
on 30 Jan 12Alexander: The controllers are just vanilla ActionController. Lots of shared module use though, especially with ActiveSupport::Concern.
Abraham
on 30 Jan 12@DHH “I still don’t like client-side MVC from a developer’s standpoint” – care to elaborate?
Roger Ertesvåg
on 30 Jan 12What do you use to test the Coffeescript code?
DHH
on 30 Jan 12Alexander, no, I’m not a fan of that at all. Our controllers differ far too much to make any of those abstractions worthwhile.
Jim, no, I would not test that validation rules exist. I test things that have enough logic to make it worthwhile and then everything else as part of functional/integration tests.
I’d be happy to write something up at some point about how I test. Obviously there are many opinions on this matter and mine is probably one of less testing than the average. Also, I rarely practice TDD on regular web stuff (but frequently for libraries/frameworks).
DHH
on 30 Jan 12Abraham, CoffeeScript is nicer, but Ruby is nicer. Also, I like the flow control of post/response from “regular” web apps. I generally don’t care much for heavy-logic views.
AstonJ
on 30 Jan 12Could you give us more info (perhaps a list of the) gems you’re using? (It’s always interesting to see which gems large Rails sites make use of.)
Also, would you consider doing a general blog post about Rails, perhaps a walk down memory lane and a step into the future? (I’d love to hear your ideas and thoughts about where it (might be) heading.)
Bart
on 30 Jan 12And how many lines of css?
Jim Ryan
on 30 Jan 12DHH, I was kind of expecting you to say that. I’ve been torn on this for a while – testing that validation rules exist is basically just testing that you wrote the line of code, and that’s wrong IMO.
I’d be very interested in reading that, and I’m sure I’m not the only one in the community. I’ve been trying BDD with RSpec and friends lately, but it hasn’t felt as natural to me as its supporters make it out to be. That’s interesting that you don’t practice TDD on web stuff, that was going to be my next question. Definitely write something up whenever you have the time. I don’t know if there’s enough material for a book, but if there is, I’d buy it!
Phil
on 30 Jan 12Why still use Memcached when you’ve already got Redis in the stack? From our performance testing on a very high-traffic app the difference between the two was negligible, but we needed some Redis features, so went with Redis only as the ops overhead of running both systems seemed redundant.
DHH
on 30 Jan 12Aston, here are the main external gems that we use: unicorn, whenever, SyslogLogger, rails_autolink, htmlentities, uuidtools, useragent, resque, eco, exception_notification, elastic, statsd-ruby.
Ben Garvey
on 30 Jan 12I can’t even imagine how Basecamp is only 2000 lines of code.
Aaron R.
on 30 Jan 12I noticed you included integration tests in your statistics, but there is basically nothing there for them. What accounts for this? Are they not being written? Are they part of a separate code base? Curious to know.
Philip
on 30 Jan 121. How do u test ur CoffeeScript? 2. Do u do any deep integration tests with Selenium or else?
Graham Siener
on 30 Jan 12Wow, thanks for sharing. Would love to hear how you handle testing for your coffeescript and backbone code.
Also, does this still represent the first use of your Cinco framework? Does that still exist as a potentially separate framework?
Scott
on 30 Jan 12Interesting:
“we have almost as much CoffeeScript as Ruby code!”
and
“We don’t do that all that much [client side]. Most of Basecamp Next is still server side generated.” – https://twitter.com/#!/dhh/status/163984450982649856
Neil
on 30 Jan 12I’d be interested in hearing what types of interactions you felt using backbone.js came in handy (vs. the ones you didn’t).
Alexander Tipugin
on 30 Jan 12Are you use libraries like Compass or Bourbon for frontend stuff?
Jacob Riff
on 30 Jan 12“Also, I rarely practice TDD on regular web stuff (but frequently for libraries/frameworks).”
I for one would LOVE to read such a post. I omit TDD for web stuff too and I always feel like I am “cheating”. A post from you would perhaps help :-)
Matt
on 30 Jan 12What mysql storage engine are you guys using? Curious how it works with the SSD drives.
Vojtech
on 30 Jan 12Are you using local storage to cache objects on the client side?
Vojtech
on 30 Jan 12Sorry for posting twice, but I just remembered:
Are you going to share some of the CoffeeScript code as an open-source library for others to use? Sounds like some of those 5,000 lines are libraries that could be helpful to everybody.
Chris
on 30 Jan 12I think I have the same question as Scott.
If you don’t have much client-side MVC and only 24 Eco templates, what is all the CoffeeScript?
Tom
on 30 Jan 12+1 for an article on how 37 Signals tests!
DHH
on 30 Jan 12Scott, Chris, we spruce up HTML being rendered server side with all sorts of dynamic behavior using CoffeeScript. But we don’t do HTML generation client-side and just shoot json across the wire, mostly.
Jhimy
on 30 Jan 12Dhh, do you guys use some tool for test automation? Something like guard/autotest/etc.
Jordan
on 30 Jan 12Wow… those code counts are reason enough to learn RoRs.
(I mostly help companies cleanup codebases built in PHP frameworks, and am used to production quality apps requiring 20K – 30K lines, not including tests)
Karel
on 30 Jan 12@DHH: What’s the “elastic” gem you’ve mentioned?
DHH
on 30 Jan 12Jhimy, we don’t.
Karel, we use Elastic Search.
re: JS testing, we don’t have anything good besides some selenium tests. Heavy UI code is hard to test any other way. We’re still looking for good alternatives.
SS
on 30 Jan 12We are testing the calendar UI with a home-rolled CoffeeScript test runner that operates inside the browser.
Nick
on 30 Jan 12I’d also love to see a post on how unit and integration tests are done under 37 signals. :) Testing is an essential part of the app development process and I believe revealing the 37 singles app development process would greatly benefit the ecosystem as a whole.
Karel
on 30 Jan 12@DHH: Nice to hear that! But which gem/lib, I don’t know about any “elastic” gem out there?
Eduardo Sampaio
on 30 Jan 12@Karel I think DHH meant https://github.com/socialcast/elastic_searchable
SS
on 30 Jan 12The
elastic
gem is our own client for ElasticSearch’s JSON API.Grant
on 30 Jan 12@SS Any plans to open source it?
Karel
on 30 Jan 12@SS, thanks for clarification!
Handi
on 31 Jan 12How about your API strategy? Totally separate from web and the web just consumer of API? or same application but different namespace? or just same controller?
Thanks.
Kendall
on 31 Jan 12DHH,
Since learning Backbone, I feel naturally inclined to putting most logic and templates directly into the client framework. What are the downsides of this approach? So far, I feel like I’ve encountered very few.
For you, is it just a preference, or is there something deeper?
JH
on 31 Jan 12Handi, same application, but different controllers with a different namespace.
Al Abut
on 31 Jan 12What is it about the calendar that makes you code for it differently client-side?
Angelo
on 31 Jan 12Hi Guys, which linux distribution in your servers?
GeeIWonder
on 31 Jan 12This is a horrible sentence that could easily pass as a case study in irony.
Alexis
on 31 Jan 12Do you also test JavaScript, or coffee ?
Do you run any other metrics in order to keep the code healthy ?
Tekin
on 31 Jan 12I’m really surprised at the lack of integration tests here. Are full-stack integration tests not part of the 37signals development process? I find them invaluable for catching regressions, especially with JavaScript heavy UI.
Gareth Rees
on 31 Jan 12Do you fix the rails gem version you use or do you pull in updates regularly? I’m looking for a way to semi-automatically keep my apps up to date with rails without having to remember to manually bundle update every month.
DHH
on 31 Jan 12Gareth, we use branch: ‘3-2-stable’ in the Gemfile and then occasionally we’ll do bundle update rails to get the latest.
DHH
on 31 Jan 12Tekin, full integration tests ala selenium are quite brittle when there’s rapid churn on the design, so we haven’t done much yet. Now that the design is calming down, it’s time to add more.
As Sam mentions, we’ve also started exploring other forms of JS testing.
Richy
on 01 Feb 12You said that there are about 5,000 CoffeeScript lines of code and I wonder how much is about the views? Such as erb. In fact, I think CoffeeScript is a sort of view code and erb(or html) is another code of view.
Alexander Tipugin
on 01 Feb 12One deadly simple question – do you use ruby 1.9 new syntax or stay with old-good-rocket-style hashes etc?
TDL
on 01 Feb 12Wondering which storage engine you’re using for MySQL: MyISAM, InnoDB, other?
Regarding the move to ElasticSearch, what drove this? Better performance / JSON api / flexibility (schema-less indexing) ?
TDL
on 01 Feb 12Great post by the way, loving the juicy technical details :)
Joe Fiorini
on 02 Feb 12David,
You said “I like the flow control of post/response from “regular” web apps. I generally don’t care much for heavy-logic views” earlier in response to your feelings on client-side MVC. I’ve always felt that “from a developer’s standpoint” client-side MVC leads to a cleaner separation of concerns, so I’m curious a) why is post/response better and b) how do client-side MVC frameworks lead to “logic-heavy” views? I assume by views you mean templates and I find it easier to create lightweight client-side templates than server-side ones.
Enjoying this comment thread, thanks!
Artan
on 02 Feb 12Do you use a services layer or something similar, and what do you think of the opinion that many features in Rails are not object-oriented, such as helpers, etc.
I personally dislike services layer.
justting
on 06 Feb 12It is important to dress appropriately for the season, as well as to tie into the rest of the wedding when you are the Mother of the bride. The type of neckline, length, material and style of your dress or outfit all need to be taken into account when deciding what you desire and what will best suit the day.
In winter it is important to choose an outfit that will keep you warm, while still allowing you to look stylish. This can be done in a number of ways including careful choosing of the type of neckline, length and material as well as style.
Choosing a neckline
Whether you are wearing a dress or a pantsuit, you can afford to go a little daring with the neckline even in the winter if you desire. Wearing a long dress coupled with short sleeves or a revealing neckline will still keep you warm, as will covering up your shoulders with a shawl or a jacket.
Choice of neckline is mostly about what you feel comfortable with. Many different types of neckline are available, with strapless, Sweetheart and spaghetti straps being the most common. A strapless couples very well with a wrap or a jacket, creating a stylish image that is not compromised by the presence of distracting straps.
Another option is square neckline. This is popular on long sleeved dresses, and shows some skin while not being revealing. This is a good option if you are worried about cleavage, or want to ensure you stay warm, as there is not a lot of skin that is uncovered.
For a more unusual look, a dress with an asymmetrical neckline is worth considering. These can be elegant and draw attention to your features. Often, an asymmetrical neckline will consist of a strap over one shoulder, but no mirroring strap over the other.
What length?
Choosing a longer dress style is a good choice during the winter, as it allows you to keep warm even if your arms or shoulders are a little bare. A long dress can be coupled with short sleeves or a more revealing neckline, as the material from the skirt will serve to keep you warm, and the overall appearance is one of elegance and sophistication.
Importance of material choice
Dresses for the mother of the bride can be in any number of materials, such as satin, taffeta, lace and tulle. Choice of material is important in ensuring that you will be both warm and comfortable. Choosing a heavier fabric will work well, however, most winter weddings are inside due to the extremes of winter weather, so a heavy duty fabric is often not necessary. Instead, choosing a that is layered, or either a top or skirt that is, can increase warmth without the need to resort to heavy fabric.
Choosing a style for you
A layered dress or top is a good way of keeping warm in the winter while still retaining an elegant appearance. The extra layers help to trap the heat while they also are flattering.
Embellishments, such as sequins and embroidery as well as the use of jewelry and the type of sleeves can all add to the individuality of your dress/outfit, resulting in the appearance that you desire. Sequins and embroidery can be hand stitched to dresses, creating an individualized look, whether you desire a contemporary or a traditional look.
A final part of your outfit is the shoes. If your shoes are covered by your dress, choose something warm and comfortable. If they are not, consider how they match your dress and how warm they will be.
This discussion is closed.