Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Code Smells: Your Refactoring Cheat Codes

Code Smells: Your Refactoring Cheat Codes

Sure, the TDD cycle is red-green-refactor but what exactly are we refactoring? We just wrote the code, it's green, and it seems reasonable to us. Let's move onto the next test. We're have a deadline, remember?

Whether we're working with code we just wrote or opening up a project for the first time, being able to listen to the hints the code is trying to give you about how it wants to be constructed is the most direct path toward successful refactoring. What the code is telling you nuanced however: no code smell is absolute and none in itself is an indication of a problem. How do we know we need to refactor? What are the code smells telling us to do? How do we balance our short terms needs of shipping our software with the long term maintainability of the code base? In this talk we'll talk through some of the classical code smells and dive into examples of how to put these smells to work for you.

John Pignata

April 04, 2013
Tweet

More Decks by John Pignata

Other Decks in Programming

Transcript

  1. queue = Queue.new client = HTTPClient.new socket = UDPSocket.new 10.times

    do Thread.new do while data = queue.pop client.post("https://android.googleapis.com/gcm/send", data, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end socket.bind("0.0.0.0", 6889) while data = socket.recvfrom(4096) case data[0].split.first when "PING" socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) queue << json end end
  2. PING it responds with PONG SEND it delivers the message

    to the Google Cloud Messaging API Commands
  3. PING ✔ it responds with PONG SEND it delivers the

    message to the Google Cloud Messaging API Commands
  4. PING ✔ it responds with PONG SEND ✔ it delivers

    the message to the Google Cloud Messaging API Commands
  5. describe "Push Daemon" do let(:socket) { UDPSocket.new } before(:all) do

    Thread.new { load "./pushd.rb" } end describe "commands" do describe "PING" do it "responds with PONG" end describe "SEND" do it "delivers the message to the Google Cloud Messaging API" end end end
  6. it "responds with PONG" do socket.send("PING", 0, "127.0.0.1", 6889) response,

    _ = socket.recvfrom(8) response.should eq("PONG") end
  7. it "delivers the message to the Google Cloud Messaging API"

    do stub_request :post, "https://android.googleapis.com/gcm/send" socket.send('SEND t0k3n "Steve: What is up?"', 0, "127.0.0.1", 6889) assert_requested :post, "https://android.googleapis.com/gcm/send", { body: { "registration_ids" => ["t0k3n"], "data" => { "alert" => "Steve: What is up?" } }.to_json } end
  8. jp@oeuf:~/workspace/mwrc(master)$ rspec Push Daemon commands PING responds with PONG SEND

    delivers the message to the Google Cloud Messaging API Finished in 0.06854 seconds 2 examples, 0 failures
  9. queue = Queue.new client = HTTPClient.new socket = UDPSocket.new 10.times

    do Thread.new do while data = queue.pop client.post("https://android.googleapis.com/gcm/send", data, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end socket.bind("0.0.0.0", 6889) while data = socket.recvfrom(4096) case data[0].split.first when "PING" socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) queue << json end end
  10. queue = Queue.new client = HTTPClient.new socket = UDPSocket.new 10.times

    do Thread.new do while data = queue.pop client.post("https://android.googleapis.com/gcm/send", data, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end socket.bind("0.0.0.0", 6889) while data = socket.recvfrom(4096) case data[0].split.first when "PING" socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) queue << json end end Collaborator Instantiation [
  11. queue = Queue.new client = HTTPClient.new socket = UDPSocket.new 10.times

    do Thread.new do while data = queue.pop client.post("https://android.googleapis.com/gcm/send", data, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end socket.bind("0.0.0.0", 6889) while data = socket.recvfrom(4096) case data[0].split.first when "PING" socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) queue << json end end Thread Pool Initialization [ Collaborator Instantiation [
  12. queue = Queue.new client = HTTPClient.new socket = UDPSocket.new 10.times

    do Thread.new do while data = queue.pop client.post("https://android.googleapis.com/gcm/send", data, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end socket.bind("0.0.0.0", 6889) while data = socket.recvfrom(4096) case data[0].split.first when "PING" socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) queue << json end end Thread Pool Initialization [ Service Request Creation and Delivery [ Collaborator Instantiation [
  13. queue = Queue.new client = HTTPClient.new socket = UDPSocket.new 10.times

    do Thread.new do while data = queue.pop client.post("https://android.googleapis.com/gcm/send", data, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end socket.bind("0.0.0.0", 6889) while data = socket.recvfrom(4096) case data[0].split.first when "PING" socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) queue << json end end Thread Pool Initialization [ Service Request Creation and Delivery [ [ Server Socket Setup Collaborator Instantiation [
  14. queue = Queue.new client = HTTPClient.new socket = UDPSocket.new 10.times

    do Thread.new do while data = queue.pop client.post("https://android.googleapis.com/gcm/send", data, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end socket.bind("0.0.0.0", 6889) while data = socket.recvfrom(4096) case data[0].split.first when "PING" socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) queue << json end end Thread Pool Initialization [ Service Request Creation and Delivery [ [ Server Socket Setup [ Command Dispatch Collaborator Instantiation [
  15. queue = Queue.new client = HTTPClient.new socket = UDPSocket.new 10.times

    do Thread.new do while data = queue.pop client.post("https://android.googleapis.com/gcm/send", data, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end socket.bind("0.0.0.0", 6889) while data = socket.recvfrom(4096) case data[0].split.first when "PING" socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) queue << json end end Thread Pool Initialization [ Service Request Creation and Delivery [ [ Server Socket Setup [ Command Dispatch [ Parameter Extraction Collaborator Instantiation [
  16. queue = Queue.new client = HTTPClient.new socket = UDPSocket.new 10.times

    do Thread.new do while data = queue.pop client.post("https://android.googleapis.com/gcm/send", data, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end socket.bind("0.0.0.0", 6889) while data = socket.recvfrom(4096) case data[0].split.first when "PING" socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) queue << json end end Thread Pool Initialization [ Service Request Creation and Delivery [ [ Server Socket Setup [ Command Dispatch [ Parameter Extraction Collaborator Instantiation [
  17. queue = Queue.new client = HTTPClient.new socket = UDPSocket.new 10.times

    do Thread.new do while data = queue.pop client.post("https://android.googleapis.com/gcm/send", data, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end socket.bind("0.0.0.0", 6889) while data = socket.recvfrom(4096) case data[0].split.first when "PING" socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) queue << json end end
  18. 10.times do Thread.new do while json = queue.pop client.post("https://android.googleapis.com/gcm/send", json,

    "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" ) end end end socket.bind("0.0.0.0", 6889) while data = socket.recvfrom(4096) case data[0].split.first when "PING" socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) queue << json end end
  19. def start 10.times do Thread.new do while json = @queue.pop

    @client.post("https://android.googleapis.com/gcm/send", json, "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" ) end end end @socket.bind("0.0.0.0", 6889) while data = @socket.recvfrom(4096) case data[0].split.first when "PING" @socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @queue << json end end end
  20. def start 10.times do Thread.new do while json = @queue.pop

    @client.post("https://android.googleapis.com/gcm/send", json, "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" ) end end end @socket.bind("0.0.0.0", 6889) while data = @socket.recvfrom(4096) case data[0].split.first when "PING" @socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @queue << json end end end [ Spawn Workers [ Bind [ Loop and Process Incoming Requests
  21. def spawn_workers 10.times do Thread.new do while json = @queue.pop

    @client.post("https://android.googleapis.com/gcm/send", json, "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" ) end end end end
  22. def process_request data = @socket.recvfrom(4096) case data[0].split.first when "PING" @socket.send("PONG",

    0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @queue << json end end
  23. class PushDaemon def initialize @queue = Queue.new @client = HTTPClient.new

    @socket = UDPSocket.new end def start spawn_workers bind loop { process_request } end private def spawn_workers; end def bind; end def process_request; end end
  24. ➡ Update authorization key ➡ Increase thread pool size ➡

    Swap HTTP client ➡ Use a different transport protocol ➡ Modify wire protocol format ➡ Add commands ➡ Add a different push notification service ➡ Move UDP port ➡ Use x-www-form-urlencoded instead of JSON ➡ Lower maximum payload size ➡ Bind to a specific interface address ➡ Update push service URL
  25. def spawn_workers 10.times do Thread.new do while json = @queue.pop

    @client.post("https://android.googleapis.com/gcm/send", json, "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" ) end end end end
  26. def process_request data = @socket.recvfrom(4096) case data[0].split.first when "PING" @socket.send("PONG",

    0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @queue << json end end
  27. def process_request data = @socket.recvfrom(4096) case data[0].split.first when "PING" @socket.send("PONG",

    0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @queue << json end end
  28. def process_request data = @socket.recvfrom(4096) case data[0].split.first when "PING" @socket.send("PONG",

    0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end
  29. def spawn_workers 10.times do Thread.new do while json = @queue.pop

    @client.post("https://android.googleapis.com/gcm/send", json, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end end
  30. class Worker def initialize @queue = Queue.new @client = HTTPClient.new

    end def spawn(count) count.times do Thread.new do while json = @queue.pop @client.post("https://android.googleapis.com/gcm/send", json, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end end def <<(json) @queue << json end end
  31. class PushDaemon def initialize @worker = Worker.new @socket = UDPSocket.new

    end def start spawn_workers bind loop { process_request } end private def spawn_workers; end def bind; end def process_request; end end
  32. class PushDaemon def initialize @worker = Worker.new @socket = UDPSocket.new

    end def start @worker.spawn(10) bind loop { process_request } end private def bind; end def process_request; end end
  33. class PushDaemon def initialize @worker = Worker.new @socket = UDPSocket.new

    end def start @worker.spawn(10) bind loop { process_request } end private def bind; end def process_request; end end
  34. def bind @socket.bind("0.0.0.0", 6889) end def process_request data = @socket.recvfrom(4096)

    case data[0].split.first when "PING" @socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end [ Bind [ Receive [ Send
  35. def bind @socket.bind("0.0.0.0", 6889) end def process_request data = @socket.recvfrom(4096)

    case data[0].split.first when "PING" @socket.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end [ Bind [ Receive [ Send
  36. class UDPServer def initialize @socket = UDPSocket.new end def bind(port)

    @socket.bind("0.0.0.0", port) end def receive @socket.recvfrom(4096) end def send(message, address, port) @socket.send(message, 0, address, port) end end
  37. class PushDaemon def initialize @worker = Worker.new @socket = UDPSocket.new

    end def start @worker.spawn(10) bind loop { process_request } end private def bind; end def process_request; end end
  38. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new

    end def start @worker.spawn(10) bind loop { process_request } end private def bind; end def process_request; end end
  39. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new

    end def start @worker.spawn(10) bind loop { process_request } end private def bind; end def process_request; end end
  40. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new

    end def start @worker.spawn(10) @server.bind(6889) loop { process_request } end private def process_request; end end
  41. def process_request data = @socket.recvfrom(4096) case data[0].split.first when "PING" @socket.send("PONG",

    0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @queue << json end end
  42. def process_request data = @server.receive case data[0].split.first when "PING" @server.send("PONG",

    data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @queue << json end end
  43. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new

    end def start @worker.spawn(10) @server.bind(6889) loop { process_request } end private def process_request data = @server.receive case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  44. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new

    end def start @worker.spawn(10) @server.bind(6889) loop { process_request } end private def process_request data = @server.receive case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  45. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.bind(6889) loop { process_request } end private def process_request data = @server.receive case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  46. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.bind(6889) loop { process_request } end private def process_request data = @server.receive case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  47. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.bind(6889) @server.listen end private def process_request data = @server.receive case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  48. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.bind(6889) @server.listen end private def process_request data = @server.receive case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  49. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end private def process_request data = @server.receive case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  50. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end private def process_request data = @server.receive case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  51. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def process_request(data) case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  52. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def process_request(data) case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  53. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(data) case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  54. class UDPServer def initialize @socket = UDPSocket.new end def bind(port)

    @socket.bind("0.0.0.0", port) end def receive @socket.recvfrom(4096) end def send(message, address, port) @socket.send(message, 0, address, port) end end
  55. class UDPServer def initialize(app) @app = app @socket = UDPSocket.new

    end def bind(port) @socket.bind("0.0.0.0", port) end def receive @socket.recvfrom(4096) end def send(message, address, port) @socket.send(message, 0, address, port) end end
  56. class UDPServer def initialize(app) @app = app @socket = UDPSocket.new

    end def bind(port) @socket.bind("0.0.0.0", port) end def receive @socket.recvfrom(4096) end def send(message, address, port) @socket.send(message, 0, address, port) end end
  57. class UDPServer def initialize(app) @app = app @socket = UDPSocket.new

    end def listen(port) @socket.bind("0.0.0.0", port) loop { @app.call(receive) } end def receive @socket.recvfrom(4096) end def send(message, address, port) @socket.send(message, 0, address, port) end end
  58. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(data) case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  59. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(data) case data[0].split.first when "PING" @server.send("PONG", 0, data[1][3], data[1][1]) when "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end end
  60. def call(data) case data[0].split.first when "PING" @server.send("PONG", data[1][3], data[1][1]) when

    "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end
  61. module Jobs class Ping def initialize(data, server) @data = data

    @server = server end def run @server.send("PONG", @data[1][3], @data[1][1]) end end end
  62. def call(data) case data[0].split.first when "PING" @server.send("PONG", data[1][3], data[1][1]) when

    "SEND" data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end
  63. def call(data) case data[0].split.first when "PING" Jobs::Ping.new(data, @server).run when "SEND"

    data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end
  64. def call(data) case data[0].split.first when "PING" Jobs::Ping.new(data, @server).run when "SEND"

    data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) @worker << json end end
  65. module Jobs class Send def initialize(data, server) @data = data

    @server = server end def run @data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) end end end
  66. def call(data) case data[0].split.first when "PING" Jobs::Ping.new(data, @server).run when "SEND"

    json = Jobs::Send.new(data, @server).run @worker << json end end
  67. class Worker def initialize @queue = Queue.new @client = HTTPClient.new

    end def spawn(count) count.times do Thread.new do while json = @queue.pop @client.post("https://android.googleapis.com/gcm/send", json, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end end def <<(json) @queue << json end end
  68. class Worker def initialize @queue = Queue.new @client = HTTPClient.new

    end def spawn(count) count.times do Thread.new do while json = @queue.pop @client.post("https://android.googleapis.com/gcm/send", json, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end end def <<(json) @queue << json end end
  69. module Jobs class Send def self.client @client ||= HTTPClient.new end

    def initialize(data, server) @data = data @server = server end def run @data[0][5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) self.class.client.post("https://android.googleapis.com/gcm/send", json, { "Authorization" => "key=AIzaSyCABSTd47XeIH-ERx9rvHUSF9DIJ7DCwdk", "Content-Type" => "application/json" }) end end end
  70. class Worker def initialize @queue = Queue.new end def spawn(count)

    count.times do Thread.new { work } end end def <<(job) @queue << job end private def work while job = @queue.pop job.run end end end
  71. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(data) case data[0].split.first when "PING" Jobs::Ping.new(data, @server).run when "SEND" json = Jobs::Send.new(data, @server).run @worker << json end end end
  72. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(data) job = case data[0].split.first when "PING" Jobs::Ping.new(data, @server) when "SEND" Jobs::Send.new(data, @server) end if job @worker << job end end end
  73. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.bind(6889) @server.listen end def call(data) job = case data[0].split.first when "PING" Jobs::Ping.new(data, @server) when "SEND" Jobs::Send.new(data, @server) end if job @worker << job end end end
  74. module Jobs JOBS = { "PING" => Ping, "SEND" =>

    Send } def self.factory(data, server) command = data[0].split.first.upcase klass = JOBS[command] if klass klass.new(data, server) end end end
  75. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.bind(6889) @server.listen end def call(data) job = case data[0].split.first when "PING" Jobs::Ping.new(data, @server) when "SEND" Jobs::Send.new(data, @server) end if job @worker << job end end end
  76. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(data) job = Jobs.factory(data, @server) if job @worker << job end end end
  77. module Jobs class Ping def initialize(data, server) @data = data

    @server = server end def run @server.send("PONG", @data[1][3], @data[1][1]) end end end
  78. class Client def initialize(sockaddr) @addrinfo = Addrinfo.new(sockaddr) end def address

    @addrinfo.ip_address end def port @addrinfo.ip_port end end
  79. class UDPServer def initialize(app) @app = app @socket = UDPSocket.new

    end def listen(port) @socket.bind("0.0.0.0", port) loop { @app.call(receive) } end def receive @socket.recvfrom(4096) end def send(message, address, port) @socket.send(message, 0, address, port) end end
  80. class UDPServer def initialize(app) @app = app @socket = UDPSocket.new

    end def listen(port) @socket.bind("0.0.0.0", port) loop do message, sockaddr = @socket.recvfrom(4096) client = Client.new(sockaddr) @app.call(client, message) end end def send(message, address, port) @socket.send(message, 0, address, port) end end
  81. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(data) job = Jobs.factory(data, @server) if job @worker << job end end end
  82. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(data) job = Jobs.factory(data, @server) if job @worker << job end end end
  83. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(client, message) job = Jobs.factory(client, message, @server) if job @worker << job end end end
  84. module Jobs class Ping def initialize(client, message, server) @client =

    client @message = message @server = server end def run @server.send("PONG", @client.address, @client.port) end end end
  85. class Client def initialize(sockaddr) @addrinfo = Addrinfo.new(sockaddr) end def address

    @addrinfo.ip_address end def port @addrinfo.ip_port end end
  86. class Client def initialize(sockaddr, server) @addrinfo = Addrinfo.new(sockaddr) @server =

    server end def address @addrinfo.ip_address end def port @addrinfo.ip_port end end
  87. class Client def initialize(sockaddr, server) @addrinfo = Addrinfo.new(sockaddr) @server =

    server end def send(message) @server.send(message, address, port) end def address @addrinfo.ip_address end def port @addrinfo.ip_port end end
  88. class UDPServer def initialize(app) @app = app @socket = UDPSocket.new

    end def listen @socket.bind("0.0.0.0", port) loop do message, sockaddr = @socket.recvfrom(4096) client = Client.new(sockaddr) @app.call(client, message) end end def send(message, address, port) @socket.send(message, 0, address, port) end end
  89. class UDPServer def initialize(app) @app = app @socket = UDPSocket.new

    end def listen @socket.bind("0.0.0.0", port) loop do message, sockaddr = @socket.recvfrom(4096) client = Client.new(sockaddr, self) @app.call(client, message) end end def send(message, address, port) @socket.send(message, 0, address, port) end end
  90. module Jobs class Ping def initialize(client, message, server) @client =

    client @message = message @server = server end def run @server.send("PONG", @client.address, @client.port) end end end
  91. module Jobs class Ping def initialize(client, message, server) @client =

    client @message = message @server = server end def run @client.send("PONG") end end end
  92. module Jobs class Ping def initialize(client, message, server) @client =

    client @message = message @server = server end def run @client.send("PONG") end end end
  93. module Jobs class Ping def initialize(client, message) @client = client

    @message = message end def run @client.send("PONG") end end end
  94. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(client, message) job = Jobs.factory(client, message, @server) if job @worker << job end end end
  95. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(client, message) job = Jobs.factory(client, message) if job @worker << job end end end
  96. module Jobs class Send def self.client @client ||= HTTPClient.new end

    def initialize(client, message) @client = client @message = message end def run @message[5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) self.class.client.post("https://android.googleapis.com/gcm/send", json, { "Authorization" => "key=AIzaSyCABSTd47XeIH-ERx9rvHUSF9DIJ7DCwdk", "Content-Type" => "application/json" }) end end end
  97. module Jobs class Send def self.client @client ||= HTTPClient.new end

    def initialize(client, message) @client = client @message = message end def run @message[5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) self.class.client.post("https://android.googleapis.com/gcm/send", json, { "Authorization" => "key=AIzaSyCABSTd47XeIH-ERx9rvHUSF9DIJ7DCwdk", "Content-Type" => "application/json" }) end end end HTTP Client [ Server Client [
  98. module Jobs class Send def self.client @client ||= HTTPClient.new end

    def initialize(client, message) @client = client @message = message end def run @message[5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) json = JSON.generate({ "registration_ids" => [$1], "data" => { "alert" => $2 } }) self.class.client.post("https://android.googleapis.com/gcm/send", json, { "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" }) end end end
  99. class PushNotification def self.client @client ||= HTTPClient.new end def initialize(registration_id,

    alert) @registration_id = registration_id @alert = alert end def deliver self.class.client.post("https://android.googleapis.com/gcm/send", to_json, "Authorization" => "key=AIzaSyCABSTd47XeIH", "Content-Type" => "application/json" ) end def to_json { "registration_ids" => [@registration_id], "data" => { "alert" => @alert } }.to_json end end
  100. module Jobs class Send def initialize(client, message) @client = client

    @message = message end def run @message[5..-1].match(/([a-zA-Z0-9_\-]*) "([^"]*)/) PushNotification.new($1, $2).deliver end end end
  101. class Request def initialize(message) @tokens = Shellwords.split(message) end def command

    @tokens[0].to_s.upcase end def parameters Array(@tokens[1..-1]) end end
  102. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(client, message) job = Jobs.factory(client, message) if job @worker << job end end end
  103. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(client, message) request = Request.new(message) job = Jobs.factory(client, request) if job @worker << job end end end
  104. module Jobs JOBS = { "PING" => Ping, "SEND" =>

    Send } def self.factory(client, message) command = message.split.first.upcase klass = JOBS[command] if klass klass.new(client, message) end end end
  105. module Jobs JOBS = { "PING" => Ping, "SEND" =>

    Send } def self.factory(client, request) klass = JOBS[request.command] if klass klass.new(client, request) end end end
  106. module Jobs class Send def initialize(client, request) @client = client

    @request = request end def run PushNotification.new(registration_id, alert).deliver end private def registration_id @request.parameters[0] end def alert @request.parameters[1] end end end
  107. module Jobs JOBS = { "PING" => Ping, "SEND" =>

    Send } def self.factory(client, request) klass = JOBS[request.command] if klass klass.new(client, request) end end end Possible nil from hash [
  108. class PushDaemon def initialize @server = UDPServer.new(self) @worker = Worker.new

    end def start @worker.spawn(10) @server.listen(6889) end def call(client, message) request = Request.new(message) job = Jobs.factory(client, request) if job @worker << job end end end Possible nil from factory [
  109. module Jobs JOBS = { "PING" => Ping, "SEND" =>

    Send } def self.factory(client, request) klass = JOBS[request.command] if klass klass.new(client, request) end end end
  110. module Jobs JOBS = { "PING" => Ping, "SEND" =>

    Send } JOBS.default = NullJob def self.factory(client, request) JOBS[request.command].new(client, request) end end
  111. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(client, message) request = Request.new(message) job = Jobs.factory(client, request) if job @worker << job end end end
  112. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(client, message) request = Request.new(message) job = Jobs.factory(client, request) @worker << job end end
  113. module Jobs class Ping def initialize(client, request) @client = client

    @request = request end def run @client.send("PONG") end def >>(worker) worker << self end end end
  114. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(client, message) request = Request.new(message) job = Jobs.factory(client, request) @worker << job end end
  115. class PushDaemon def initialize @worker = Worker.new @server = UDPServer.new(self)

    end def start @worker.spawn(10) @server.listen(6889) end def call(client, message) request = Request.new(message) job = Jobs.factory(client, request) job >> @worker end end