Extreme isolation in web apps
chrismdp.comThis must be the Ruby equivalent of the once prevalent Java pattern craze, I mean what the hell is the purpose of a class like this:
class JoiningError < Struct.new(:message)
def effect(caller)
caller.joining_error(self)
end
endThe purpose is to avoid a big case statement:
It's actually not implemented like that under the hood: it's done using a module with a `send`.case(change.class) when JoiningError: joining_error() when SomethingElse: something_else() ... endI don't get it at all. Here is the whole thing in straightforward 80's OOP:
Could you explain to me how is the version presented an improvement over such a straightforward one?post '/join/?' do game_server = GameServer.instance if game_server.join(params[:name], @account.id) flash[:notice] = "You have joined the game." redirect_to '/game' else flash[:error] = "There was an error when joining: #{change.message}" haml :join end end class GameServer include Singleton def initialize @games = [Game.new] end def join(name, account_id) player = Player.new(name, account_id) return @games.last.joined_by(player) end end class Player < Struct.new(:name, :account_id) end class Game def initialize @players = [] @events = [] end def joined_by(player) if @players.none? { |player| player.name == player.name } @players << player @events << PlayerJoined.new return true else @events << JoiningError.new return false end end end class Event end class PlayerJoined < Event end class JoiningError < Event endThere's no persistence in your example: how would you plug that in?
If I would see any purpose in striving for this level of separation I would use the DataMapper pattern (http://martinfowler.com/eaaCatalog/dataMapper.html), but I do not see it, so the Player etc. models would probably be ActiveRecords.
I've written lots of web apps using the plain ActiveRecord approach, and I've found it scales well to a given level of complexity, and then becomes hard to manage - hence trying something different.