ruby - Why is global state bad? -


i had talk on #ruby-lang channel other day @@class_variables. started when user asked what's best way keep track of connected users server (i simplified it, that's gist of it).

so, suggested:

class user   @@list = {} #assuming wants users type of id    def initialize(user_id, ...)     @@list[user_id] = self     #...   end end 

however, somone said use of global state here considered bad practice.

i understand why global state bad relies on multiple back-ends, because global part of global state stops being global, , becomes localised 1 back-end. or interferes dependency injection.

i can't think of other reason why bad, though. and, if concurrency ever becomes issue (there's need multiple back-ends), can update code use redis (or similar).

also, found this question on programmers.sxc, doesn't me understand why above code considered bad? also, alternative?

why bad?

global state bad couple of reasons didn't mention:

  1. it's unreliable: because in program, including third party code, can change variable, can never depend on being there 1 second after put in.
  2. it breaks encapsulation: if have global list of users, other parts of program should have go through user class access it. otherwise, manipulating data directly, bad idea.
  3. hard change: if find out global state needs be, say, array instead of hash, bad luck. have change every part of code uses because there no accessors change.
  4. this 1 little more abstract, still: function purity: when introduce global state, many pure functions become impure. bad in general, because compiled languages c can heavily optimize pure functions, , bad in ruby because makes methods harder test.

the specific form of global state mention, @@ variables, bad ruby specific reason:

  • it has weird inheritance semantics: @@ variables in ruby shared between class , it's subclasses. though think encapsulated, isn't. bad if subclasses user class, , declares variable @@list storing unrelated data. ruby won't complain, , state of entire user class tree compromised.

what else can done?

  • dependancy injection: pass around data whoever needs without ever maintaining globally.
  • class encapsulation: if need global state, have class maintain setters , getters. invalidates points 2 , 3, along @@ probelm because uses class @ variables. example:

    class user   class << self     @list = {}     def add_user(uid, user)       #do validation here       @list[uid] = user     end     #more methods add_user   end   def initialize(user_id, ...)     user.add_user(user_id, self)   end end 

Comments

Popular posts from this blog

java.util.scanner - How to read and add only numbers to array from a text file -

rewrite - Trouble with Wordpress multiple custom querystrings -