Help me with my architecture - global variables in Ruby on Rails - 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/

Related

Why are unnecessary instance variables a bad practice?

I have heard several times that creating unnecessary instance variables is bad practice, but can't figure out why it is a bad practice?
What effects does it have if we use unnecessary instance variables in our application?
Any help would be appreciated, thanks in advance.
Because they are unnecessary but they will still float around in your views.
The catch is, you know that they are unnecessary so you won't care about them (even if they contain wrong data) but next developers won't know that they are unnecessary. He would think that there is some important reason that is why kartik defined them. He might go ahead and use them and may end up using wrong data.
Poor guy will have to struggle a lot to understand the reason of their existence. And when he will know then he may curse you :)
Using instance variable everywhere is not a wise thing to do. You can think of global variables (on a smaller scale) as an analogy. There are often methods that have data very specific to them. Sharing them across with all the methods of the object does not make sense, when you can directly pass them to specific methods as parameters. Also this may potentially lead to un-debuggable spaghetti code.
If I were you I would like to think that instance variables hold the state of my objects. Therefore I would only have to use just enough instance variables for the states I need to know or use to interact with other objects.

Why would I create a singleton in swift instead of just dumping functions in a file?

With swift, isn't it possible to dump functions and variables into a file instead of implementing a singleton? Is there a good reason (like memory management or something) that I am missing, other than style concerns?
It is very much possible to do so. Module level private variables could be used as private variables for singleton class.
For me it is rather a choice dictated by what makes more sense as a solution to the problem. The language has given us tools each with its particular usage, so use them the way they are meant to be used.
If your solution requires an object with data, state and related functionality which could have only one instance then it is better to use a singleton. This will make more sense when you or someone else will try to understand code at later time.
If your solution is just bunch of loosely related functions without data or state then it is better to use functions in a file.
With swift, isn't it possible to dump functions and variables into a file instead of implementing a singleton?
Yes, it is definitely possible. However, the same is possible in Objective-C, with the same pluses and minuses.
Is there a good reason (like memory management or something) that I am missing, other than style concerns?
Two considerations are relevant here:
You can make your singleton polymorphic, expose an interface, define several implementations, and pick the specific one at runtime
You can "reset" your singleton by discarding the instance and creating a new one.
If you need concurrency, having a singleton makes it a little easier to implement.

Data Accessor object singleton or some other pattern? (Objective C)

It seems to satisfy the three requirements here: On Design Patterns: When to use the Singleton?
I need it to exist only once.
I need to access it from all over the source base.
It handles concurrent access, i.e. Locks for writes, but can handle concurrent reads.
Hi all,
I've been reading a lot of no doubt intelligent educated and wise gems of advice that Singletons are 'Evil' and singletons are anti patterns or just plain bad news.
With the argument that logging makes sense but not much else.
Just interested to know if the case of essentially a persistent data store context makes sense for a singleton, i.e. Reading/Writing from disk to memory and referencing an object graph.
And if not, how do people normally tackle this issue, I don't currently have any problem with it, I know it's created only once, it's fast and the accessor logic is in one place. Meaning it takes me one line of code to do anything data model related.
Which leaves the only argument that it's bad for testing, in that it's a hard coded production implementation to data, but couldn't I just write a method swizzle through a category or in the test code to create the test version of the singleton?
And the final argument from DI testers, is that it is a hard coded implementation, rather than simply an interface to something, which I do get but I don't really have a major drive to use a DI framework given that I can use protocols for implementation, and use separate init methods for setting up an objects state in testing. There's only ever going to be two types of state for the singleton, or realistically one type...production.
Making it (in my opinion) much easier to read and faster to develop.
Change my view SO?
Yup, for some singletons are Evil. For the new developers who has little MRC knowledge and more ARC it sounds scary because they need to mess with memory,volatile,synchronize etc.
However it is not against to use them, they indeed has their own purpose to use with some are below.
when sharing large data models like arrays and dictionaries etc between multiple screens (VC's) we can't prefer storing them in UserDefaults (because userdefaults is permanent storage and storing such large entries make app start lazily) instead singletons are best since they stay only current app context and restarting app creates new one.
when we need a stable db connection to be accessible allover the app without messing up with connecting and closing in every business classes we can go for it.
when we wanted an ability to app for theming itself dynamically we would need to create a singleton class which holds all the color,image instances etc. and use that instance in application VC/Views etc so no code duplication and re-processing theme occurs in all places.
You dont have to change your view but tweak it a bit to get some positive intention towards singletons.
Hoping this clears it out, thanks

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.

Are Ruby class member variables OK now?

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.)

Resources