初心者エンジニアの システム構築 失敗談

9,269 views

Published on

Published in: Technology
1 Comment
21 Likes
Statistics
Notes
No Downloads
Views
Total views
9,269
On SlideShare
0
From Embeds
0
Number of Embeds
2,020
Actions
Shares
0
Downloads
23
Comments
1
Likes
21
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Logic層の役割が曖昧だった\nある程度は太ってもぽっちゃり系で許容できるけど、スパゲッティにならないことが重要\nLogic層はあくまでModel\nここでカオスった\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • エラーがARの中に入ってる(ARをViewまで引き回す)\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • controller のアクション毎に設定できる\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 初心者エンジニアの システム構築 失敗談

    1. 1. 初心者エンジニア の システム構築 @Spring_MT
    2. 2. Profile
    3. 3. @Spring_MTin 10xLabInfra andApp Engineer
    4. 4. 初心者?
    5. 5. ・前職でエンジニアに転向・エンジニア歴 2年半くらい・福岡歴は10ヶ月
    6. 6. 前の環境
    7. 7. 言語 フレームワーク perl 独自フレームワークテストはあんまりない >_<
    8. 8. DB関連 databaseは複数 joinは基本しない masterとslaveautoincrement使わない
    9. 9. 新しい環境
    10. 10. なんもない。。。。
    11. 11. 0からスタート
    12. 12. フレームワーク
    13. 13. ・テスト周りの環境が ってる・新しくjoinする人(学生含めて)の学習コストが低い
    14. 14. Rails
    15. 15. 実際はやってみた
    16. 16. Rails で
    17. 17. はじめの一歩
    18. 18. 課題
    19. 19. ・複数DB対応・master slave振り分け・採番(sequence)・belongs_toの扱い
    20. 20. えっ。。。
    21. 21. いきなり大きいこと考えすぎでもこの時は必要だと思ったんです。。。。
    22. 22. 大規模病>_<
    23. 23. 複数DBの対応master・slave振り分け
    24. 24. 方針・DB + master、slave毎にmodelを作る・Controllerで明示的にDBア
    25. 25. class TestMasterShard < ActiveRecord::Base self.abstract_class = true establish_connection "#{ENV[RAILS_ENV]}_test_master"endclass FooMaster < TestMasterShard self.table_name = foo attr_accessible :name validates :content_id, {presence: true}end
    26. 26. octopus・テストではまる・明示的に書いたほうがトラブルが少なそう
    27. 27. # config.include RSpec::Octopusconfig.before do shards = ActiveRecord::Base.connection_proxy.instance_variable_get(:@shards) @connections = shards.values.map(&:connection) @connections.each do |connection| connection.increment_open_transactions connection.transaction_joinable = false connection.begin_db_transaction endendconfig.after do @connections.each do |connection| if connection.open_transactions != 0 connection.rollback_db_transaction connection.decrement_open_transactions end endend
    28. 28. View Controller Model UserController UserMaster master UserSlave slave FeedController FeedMaster master FeedSlave slave GroupControlle GroupMaster master GroupSlave slave
    29. 29. 採番
    30. 30. 方針アプリ内で一意のIDを発行する
    31. 31. ・IDがわかれば、それに紐付くデータが一意に決まる・重複が起きないex) user_id + コンテンツ
    32. 32. class Sequence < SequenceShard self.table_name = seq def self.generate(model) result = self.connection.execute( "UPDATE seq SET id=LAST_INSERT_ID(id+1)" ) id = self.connection.last_inserted_id(result) or raise RuntimeError return id endend
    33. 33. belongs_to
    34. 34. 方針今回は複数DBを想定したので使わないことにしました>_<
    35. 35. 課題・Controllerからはmasterslaveを意識せずに使いたい・ Fat Model
    36. 36. いきなりこの時点でスケールを考えている。。。そもそも考慮する必要があったのか?
    37. 37. 自分で見えない敵を作ってた。。。
    38. 38. 大規模病>_<
    39. 39. 第二期
    40. 40. 課題・Controllerからはmasterslaveを意識せずに使いたい・ Fat Model
    41. 41. 方針 slave・Controllerがmasterを意識せずにModelを呼び出せる・DBへデータを取得する部分とデータを加工する部分を分ける
    42. 42. 方針ModelをLogic層とData層に分ける
    43. 43. View Controller Model Logic Data UserController UserLogic UserMaster master UserSlave slave FeedController FeedLogic FeedMaster master FeedSlave GroupControlle slave GroupLogic GroupMaster master GroupSlave slave
    44. 44. Data層・DBへのアクセスを管理する層・connectionの設定や、SQLを管理するだけに留める
    45. 45. class TestMasterShard < ActiveRecord::Base self.abstract_class = true establish_connection "#{ENV[RAILS_ENV]}_test_master"endclass FooMaster < TestMasterShard self.table_name = foo attr_accessible :name validates :content_id, {presence: true} default_scope where(is_deleted: 0) scope :hoge, lambda { |foo| where(bar = ?, bar) }end
    46. 46. Logic層・Data層を組み合わせてデータの加工を行う
    47. 47. class BaseLogic include ActiveModel::MassAssignmentSecurity include ActiveRecord::AttributeAssignment include ActiveModel::Conversion include ActiveModel::Validations extend ActiveModel::Naming extend ActiveModel::Translation def persisted?; false; endendclass TestLogic < BaseLogic attr_accessor :foo attr_accessible :foo validates :foo, {presence: true, length: {maximum: 255}} def get_test_one endend
    48. 48. View Controller Model Logic Data UserController UserLogic UserMaster master UserSlave slave FeedController FeedLogic FeedMaster master FeedSlave GroupControlle slave GroupLogic GroupMaster master GroupSlave slave
    49. 49. 課題・複数のテーブルからデータを取得する場合、どこにその処理を書くかで迷う(Logic層?、Controller?)
    50. 50. 現在
    51. 51. 課題・複数のテーブルからデータを取得する場合、どこにその処理を書くかで迷う(Logic層?、Controller?)
    52. 52. 方針ControllerとModelの間に一層(Context)を追加
    53. 53. ユーザーのしたいこと DBのデータを適切な View を実現する処理の流れ 形で受け渡すのみController Context Model Logic DataUserController UserContext UserLogic UserMaster master UserSlaveFeedController FeedContext slave FeedLogic FeedMaster masterGroupController FeedSlave GroupContext slave GroupLogic GroupMaster master GroupSlave slave
    54. 54. Model Data層・DBへのアクセスをコントロールする層。発行するSQLはここでコントロールする
    55. 55. Model Logic層・Data層をコントロールする層・基本的に一つのテーブルに一つ
    56. 56. Context・ ユーザーのしたいことを実現するための処理の流れを実装する->ユーザが操作する内容ごとに実装
    57. 57. Controller・Contextで作成されたデータをViewに受け渡すcellsを使って、uriで表現されている処理のみを実装するようにしている
    58. 58. View・データを描画する・ここにロジックは書かない
    59. 59. ユーザーのしたいこと DBのデータを適切な View を実現する処理の流れ 形で受け渡すのみController Context Model Logic DataUserController UserContext UserLogic UserMaster master UserSlaveFeedController FeedContext slave FeedLogic FeedMaster masterGroupController FeedSlave GroupContext slave GroupLogic GroupMaster master GroupSlave slave
    60. 60. 課題・validationをどうする?
    61. 61. Validation
    62. 62. ・ユーザーが入力した値のチェック・DBに格納する前のデータのチェック
    63. 63. ・Railsは2つのvalidationが一緒になってる
    64. 64. 今の構成
    65. 65. ユーザーのしたいこと DBのデータを適切な View を実現する処理の流れ 形で受け渡すのみController Context Model Logic DataUserController UserContext UserLogic UserMaster master UserSlaveFeedController FeedContext slave FeedLogic FeedMaster masterGroupController FeedSlave GroupContext slave GroupLogic GroupMaster master GroupSlave slave
    66. 66. Contextが入ったことでvalidationでエラーが起きた時のARオブジェクトの受け渡しをどうするか?
    67. 67. Contextでは複数のARオブジェクトが格納されて、その中からvalidationエラーをまとめる。。。。
    68. 68. 正直面倒
    69. 69. Validation・ユーザーが入力した値のチェック・DBに格納する前のデータのチェック
    70. 70. 分ける!
    71. 71. つまり
    72. 72. Controllerでもvalidationする
    73. 73. えっ(∩゚д゚)
    74. 74. Controllerでもvalidationする
    75. 75. Controller でもvalidation
    76. 76. 言っちゃった..
    77. 77. ((((;゚
    78. 78. ・ユーザーが入力した値のチェック => Controller・DBに格納する前のデータのチェック => Model
    79. 79. Controller でもValidationするために
    80. 80. DataValidatorってのを書きました
    81. 81. DataValidatorARのvalidatorとほぼ同じバリデーションロジックを実装しています
    82. 82. params = {foo: foo, bar: bar}validator = DataValidator::Validator.new( params, {foo: {length: {is: 4}}}, {bar: {presence: true, format: {with: /A[a-zA-Z]+z/}}})unless validator.valid? @errors = validator.errorsend@errors=> { foo: ["is the wrong length (should be 4 characters)"], bar: ["cant be blank", "is invalid"]}
    83. 83. ・ユーザーの入力値=> Controllerのアクション毎にDataValidatorを使う・DBに格納する値=> Modelで
    84. 84. Controllerでvalidationした後は、ユーザーの入力値は正しい値としてみなし、DBに入れる値をチェックする時にエラーになった場合はシス
    85. 85. ユーザーのしたいこと DBのデータを適切な View を実現する処理の流れ 形で受け渡すのみController Context Model Logic Data UserController UserContextValidator UserLogic UserMaster master UserSlave FeedController FeedContext slaveValidator FeedLogic FeedMaster masterGroupController FeedSlave GroupContext slaveValidator GroupLogic GroupMaster master GroupSlave slave
    86. 86. ・この構成で落ち着いてます・これ以上は手を入れない予定
    87. 87. Railsやめちゃ いなよってつっこみはな
    88. 88. gem・data_validator・rack_session_redis_store・redis_json_serializer
    89. 89. 画像・ファイルストレージ
    90. 90. ・分散ファイルシステムを自前で作る?・色々なアプリでAPIちっくに使いたい
    91. 91. 画像・ファイル ・sinatraでappは作AWS VPC App(RoR) 成 HTTP ・閲覧権限等は本体で Nginx 管理 varnish varnish ・自前で分散ファイル sinatra sinatra app app システム構築は難しい のでS3を使用 S3
    92. 92. サーバー構成
    93. 93. オールAWS!
    94. 94. public subnet net work Gateway NAT SSLの変換 subnet subnet subnet subnet fluentd utility storage ser vice deliver proxy APPWatch redis f f f worker varnish DB + sinatra f f worker f f
    95. 95. その他・session storeにredis・queue処理はfluentd +resque=> http://spring-mt.tumblr.com/post/35097726578/fluent-plugin-resque・fluentd + GrowthForecastを
    96. 96. 時間があれば。。。。
    97. 97. なにかあれば懇親会で!
    98. 98. ご清聴ありがとうござ

    ×