Are Ruby class member variables OK now? - ruby-on-rails

Last May at Railsconf on Portland, I went to a presentation where it was argued that, in Rails, Ruby class member variables, like ##foo, are dangerous because they are inherently unthreadsafe.
I researched the question afterward and I never found a link that really fleshed out the question. I would appreciate a pointer to a good article on Rails and threads that really goes into the class member question. Also, It would be nice to know how Rail 2+ and Yarv has changed things in the regard.
Edit:
Perhaps my memory of the presentation is foggy but what I remember was that ##foo had problems beyond the usual caveats that any shared variable access must be strictly controlled. I know that there were memory leaks in the Ruby code itself that were fixed a little while ago. I'm looking for article links on Ruby shared variables and multitasking, the more in-depth, the better. *Currently I don't use class variable for anything because of this but it would be nice to be able use them in certain situations.

Any shared mutable state is inherently thread-unsafe. You need to lock all accesses to ensure that everything's safe, and ensure that everything is re-entrant. ##foo is particularly bad because it's harder to audit code because any subclass can be accessing the variable. Rails 2+ just "solved" the problem by auditing everything and making sure that mutexes and other synchronisation primitives were used where necessary.

I think they're as OK as they ever were, but still to be used with caution in a Rails environment where the class may be loaded multiple times (once per mongrel, for example, if you use mongrel) so the class member variable could vary independently within those processes.
I think there's a scoping change for ## variables in Ruby 1.9, which should probably be taken into account - we'll all be there one day.
Was there a particular use you had in mind? I thought I needed one recently, but it turned out to be a fault in my (sketchy) understanding of the topic - what I actually needed was an instance variable on the class. (I was building a module to extend a class so that I could add some AR-style declarative macro goodness.)

Related

Good or bad idea to prefix all classes with same abbreviation?

So in practically all my programs I wrote I always prefixed every class I created with the same abbreviation that was in relation to the program. So for instance say I wrote an app called GasStationDeluxe. I would make a class called GSDGasStation or GSDGasPump etc. Now I always thought that is a good idea because it would group together all thelse classes I created in intellisense to make it easier for me and other programmers to find the classes I created.
Yet, I'm reading a book called "Clean Code: A Handbook of agIle software craftsmanship" and I just read a part in a chapter where it says it's not a good idea to do that becasue auto complete will bring you back a list of tons of classes. So who else codes this way? Do you think it's a good or bad idea to code with the same prefix before each class? If yes or no, then why?
I have never done this, but you will sometimes see it done in solutions with multiple projects like GSD.App or GSD.Core
I was always that in a class called Customer.cs, you might not want to make the name field CustomeName but just Name as your already in the customer class so what is it adding. I suppose the same is true in your case of classes.
What if you want to reuse your classes elsewhere? I would say from the vast majority of code examples I come across and other peoples code I read, this isn’t common practice.
I suppose really it’s up to you and any team you work with, as long as it’s consistent.
I wonder what .net would look like if Microsoft prefixed everything!

Class Accessibility Throughout Project

When I first began working on a long iOS project, my first, I had need for a small class that was readily accessible throughout the project. At first I passed it around as a property and it became way too much of a headache.
So, even though I've seen posts here advising against it, I created that class in the AppDelegate and access it as needed through a pointer to the AppDelegate. Then, I would revisit it later.
So, it is now later, I'm approaching release of the project, and I want to deal with this issue. It works just fine as it is but if it is lousy practice I want to fix it before release.
I don't understand why it is lousy practice. Sometimes you just need a class that is readily available and these seems like as good a way as any to get it. But there could be some downside I'm not understanding.
Assuming I need this class instance (it is very lightweight but heavily used) to be accessible throughout the project (probably about 50 VCs, total), what would be a good alternative to just referencing it via the App Delegate?
TIA for comments. I hope it doesn't start a war.
There's no hard-fast rule for for this and hundreds of opinions to be had. Here's my take on it.
I don't understand why it is lousy practice. Sometimes you just need a class that is readily available and these seems like as good a way as any to get it. But there could be some downside I'm not understanding.
You're right to feel this way and yes sometimes you need a class readily available with your data. It's lousy because it is not how AppDelegate should be used. In an ideal world it shouldn't contain lots of unrelated state-data and should serve a singular purpose: delegating system calls to your app. The trick is where do you put your model so that everyone can have access to it?
Assuming I need this class instance (it is very lightweight but heavily used) to be accessible throughout the project (probably about 50 VCs, total), what would be a good alternative to just referencing it via the App Delegate?
Put your state in a class using the singleton pattern. It will ensure that only one copy of it is ever created and all your classes should be able to access it. This is a well accepted pattern in the iOS SDK (NSUserDefaults, UIApplication, etc..). Just beware of this class growing too large or doing too many things. Try your best to keep it simple and focused and the Object-Oriented Police will leave you alone.
Other resources and opinions worth considering:
http://www.cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html
Is it a bad practice to use your AppDelegate as your Singleton?
Is it good practice to use AppDelegate for data manipulation and Handling?

Wisdom says "don't use globals"

A global is a piece of data that is accessible in every context by name.
You may heard that "there is an exception to each rule".
I have been programming for several years, and before there was this "hip" of singletons, I started using global variables in my programs.
But, eventually, the programs switched to handle most variables as local, wheter classes fields, or methods fields.
It just came naturally, and it seems that a lot of developers, actually came to the same conclusion, before, after, and the same time, than me ;-)
In most O.O. programming languages, the program itself, is considered an object, and therefore a singleton.
Sometimes, several required global variables, wheter objects or non objects fields, can be encapsulated as a singleton.
Singleton as any other "better practice" or "design pattern", should be used wisely,
learn when & why are useful, and when not to apply.
Cheers.
I think the general idea is that there is not really "global" data. You may consider a program's user information (name, password, hair color) to be global, and in practice it may be. But it is conceivable (maybe using sockets) that other users might become active in the same session. You need a class (User) for this information and, now, several instances of it. And when you need this information, you need the right instance of User at hand. (The correct User object must be passed into the method, or must be available in an instance field; just getting the value from MainClass.userInfo won't work anymore.)
If you originally wrote the program with the idea that there might be multiple users and so far it's never been enhanced to handle them, your User class instance is a singleton and, in a sense, a "global" object as well. But your code will be more intelligible, and in the rare event multiple users are needed, easily upgradable.

Help me with my architecture - global variables in Ruby on Rails

I'm thinking about global variables in my rails application. I've searched the net about that, and found it (of course) flagged as a bad practice. I already knew that.
But I have not found another way than a global variable for what I need. Can an experienced Rails programmer help me ?
What I want to do is to create a new dedicated logger, for example logging to "log/audit.txt" and share it between several controllers. Of course, I would rather not have to recreate this "logger" object for every request.
For now, I create a logger in a global variable $my_logger in an initializer, and use it across my controllers.
What do you think ? Is there a better way to do that ?
Thank you.
The general OO stance against using global variables and singletons of any type -- in Rails and in all other OO habitats -- is to avoid the "slippery slope" towards not doing OO design at all. Global variables are to be avoided as much as possible, but your logger is obviously a case where a Singleton of some sort makes sense. The Rails environment is an example: you only have on Rails environment per application, and it's essentially a Singleton. Or consider Notifier.deliver...
Don't worry about where to put it if it must be global. Make a Singleton object with class methods as accessors and put it in lib or anywhere you think is appropriate (making a plugin might also be appropriate, for instance). Then you just use Logger.instance.log whatever. Of course you'll have to put in safeguards to make sure that the thing gets instantiated only once.
This SO question is extremely relevant: In Ruby on Rails how can I persist objects in memory between sessions
If you use the accepted answer, you'll be able to keep the logger in memory in production mode across requests.
However, I like the second answer...
to quote:
I wouldn't worry too much about
loading and discarding objects unless
you can come up with a benchmark that
proves it's an issue. Each request
creates an extraordinary amount of
intermediate objects as a matter of
course, and these are generally
created and destroyed in a matter of
several milliseconds.
...
Benchmark first, optimize only when
required.
Create your own custom logger class and require it when applicable.
Example here:
http://ianma.wordpress.com/2009/04/08/custom-logging-in-ruby-on-rails/

How does rails use memory?

I have been using the Rails console a fair bit lately and its making me curious. Commands like
>> app.get("/")
=> 200
>> app.html_document.to_s
make me curious about how does Rails works in memory. Can anyone explain what's going in there? What objects are getting instantiated when and when do they get destroyed?
That question is a little too complicated to answer. There's probably a ton going on, depending how complicated the app is.
Ruby allocates memory for objects it needs to create on the fly. When objects drop out of scope, they are marked unused and the garbage collector frees the memory.
However, class variables and global variables, etc can prevent objects from dropping out of scope.
I wouldn't worry about it too much. If you ever have memory issues in a production application, just switch to Ruby Enterprise and many of them will magically go away. :)
On a more general note, _why wrote an excellent piece on Ruby memory management / garbage collector some years ago.
After a little time and a lot of reading, here is a minimal answer to my own question since this is still being viewed by a steady trickle of people. Keep in mind that I am still new to Rails and this is simply my understanding of it after about two months of working with it.
What get instantiated when is effected by your environment settings because class loading (among other things) is handled quite differently in development vs production. The bare essentials can be gleaned from reading the comments the files in config/environments/
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
and
# The production environment is meant for finished, "live" apps.
# Code is not reloaded between requests
Aside from that, general flow is illustrated in all the typical MVC diagrams (dispatcher > controller > model > controller > view ) and while true, there are tonnes of other classes instantiated along the way. An exhaustive list would be exactly that, exhausting.
For those interested in the details (at least all the details that matter) but not sure where to go, the book "The Rails Way" by Obie Fernandez is very worthwhile and deals with this rather extensively.

Resources