หากเว็บแอปพลิเคชันมีขนาดใหญ่และเก่าพออาจมีบางครั้งที่คุณต้องแยกย่อยออกเป็นส่วนเล็ก ๆ แยกออกจากกันและแยกบริการออกจากแอปพลิเคชันซึ่งบางส่วนจะเป็นอิสระมากกว่าส่วนอื่น สาเหตุบางประการที่อาจกระตุ้นให้เกิดการตัดสินใจดังกล่าว ได้แก่ การลดเวลาในการเรียกใช้การทดสอบความสามารถในการปรับใช้ส่วนต่างๆของแอปโดยอิสระหรือบังคับใช้ขอบเขตระหว่างระบบย่อย การสกัดบริการจำเป็นต้องใช้วิศวกรซอฟต์แวร์ในการตัดสินใจที่สำคัญหลายอย่างและหนึ่งในนั้นคือสิ่งที่กองเทคโนโลยีที่จะใช้สำหรับบริการใหม่
ในโพสต์นี้เราแบ่งปันเรื่องราวเกี่ยวกับการแยกบริการใหม่จากแอปพลิเคชันเสาหิน - ไฟล์ แพลตฟอร์ม ApeeScape . เราอธิบายว่าเราเลือกกองเทคนิคใดและทำไมและสรุปปัญหาบางประการที่เราพบระหว่างการใช้บริการ
บริการ Chronicles ของ ApeeScape เป็นแอปที่จัดการการกระทำของผู้ใช้ทั้งหมดที่ดำเนินการบนแพลตฟอร์ม ApeeScape การดำเนินการคือรายการบันทึกเป็นหลัก เมื่อผู้ใช้ทำอะไรบางอย่าง (เช่นเผยแพร่บล็อกโพสต์อนุมัติงาน ฯลฯ ) รายการบันทึกใหม่จะถูกสร้างขึ้น
แม้ว่าจะดึงมาจากแพลตฟอร์มของเรา แต่โดยพื้นฐานแล้วไม่ได้ขึ้นอยู่กับมันและสามารถใช้กับแอปอื่น ๆ ได้ นี่คือเหตุผลที่เราเผยแพร่บัญชีรายละเอียดของกระบวนการและพูดคุยถึงความท้าทายหลายประการที่ทีมวิศวกรของเราต้องเอาชนะในขณะที่เปลี่ยนไปใช้สแต็กใหม่
มีสาเหตุหลายประการที่อยู่เบื้องหลังการตัดสินใจดึงบริการและปรับปรุงกองซ้อน:
แวบแรกดูเหมือนเป็นการริเริ่มที่ตรงไปตรงมา อย่างไรก็ตามการจัดการกับกองเทคโนโลยีทางเลือกมีแนวโน้มที่จะสร้างข้อเสียที่ไม่คาดคิดและนั่นคือสิ่งที่บทความในวันนี้มีจุดมุ่งหมายเพื่อแก้ไข
แอพ Chronicles ประกอบด้วยสามส่วนที่สามารถเป็นอิสระมากหรือน้อยและทำงานในคอนเทนเนอร์ Docker แยกกัน
วิธีการจ้างวิศวกรซอฟต์แวร์
พงศาวดารใช้เพื่อเชื่อมต่อกับฐานข้อมูลสองฐานข้อมูล:
ในขั้นตอนการแยกแอปเราได้ย้ายข้อมูลจากฐานข้อมูลแพลตฟอร์มและปิดการเชื่อมต่อแพลตฟอร์ม
เริ่มแรกเราตัดสินใจที่จะไปกับ ฮานามิ และระบบนิเวศทั้งหมดที่มีให้โดยค่าเริ่มต้น (แบบจำลองฮานามิที่สนับสนุนโดย ROM.rb , dry-rb, hanami-newrelic ฯลฯ ) การปฏิบัติตามวิธีการ 'มาตรฐาน' ในการทำสิ่งต่างๆทำให้เรามีแรงเสียดทานต่ำความเร็วในการใช้งานที่ดีและ 'Googleability' ที่ดีมากสำหรับปัญหาที่เราอาจประสบ นอกจากนี้ระบบนิเวศฮานามิยังเป็นผู้ใหญ่และเป็นที่นิยมและห้องสมุดได้รับการดูแลอย่างรอบคอบโดยสมาชิกที่เคารพนับถือของชุมชน Ruby
ยิ่งไปกว่านั้นระบบส่วนใหญ่ได้ถูกนำไปใช้ในฝั่ง Platform แล้ว (เช่น GraphQL Entry Search endpoint และการดำเนินการ CreateEntry) ดังนั้นเราจึงวางแผนที่จะคัดลอกโค้ดจำนวนมากจาก Platform ไปยัง Chronicles ตามที่เป็นอยู่โดยไม่ทำการเปลี่ยนแปลงใด ๆ นี่เป็นหนึ่งในเหตุผลสำคัญที่เราไม่ได้ใช้ Elixir เนื่องจาก Elixir ไม่ยอมให้ทำเช่นนั้น
เราตัดสินใจที่จะไม่ทำ Rails เพราะรู้สึกว่าเกินความจำเป็นสำหรับโครงการเล็ก ๆ เช่นนี้โดยเฉพาะอย่างยิ่งสิ่งต่างๆเช่น ActiveSupport ซึ่งไม่ได้ให้ประโยชน์ที่เป็นรูปธรรมมากมายสำหรับความต้องการของเรา
แม้ว่าเราจะพยายามทำตามแผนอย่างดีที่สุด แต่ในไม่ช้ามันก็ตกรางด้วยสาเหตุหลายประการ หนึ่งคือเราไม่มีประสบการณ์กับสแต็กที่เลือกตามมาด้วยปัญหาของแท้กับสแต็กเองจากนั้นก็มีการตั้งค่าที่ไม่ได้มาตรฐานของเรา (ฐานข้อมูลสองฐานข้อมูล) ในที่สุดเราก็ตัดสินใจที่จะกำจัด hanami-model
จากนั้นของฮานามิเองแทนที่ด้วย ซินาตร้า .
เราเลือก Sinatra เนื่องจากเป็นห้องสมุดที่ได้รับการดูแลอย่างสม่ำเสมอซึ่งสร้างขึ้นเมื่อ 12 ปีที่แล้วและเนื่องจากเป็นห้องสมุดที่ได้รับความนิยมมากที่สุดแห่งหนึ่งทุกคนในทีมจึงมีประสบการณ์โดยตรงกับห้องสมุดนี้
การสกัด Chronicles เริ่มต้นในเดือนมิถุนายน 2019 และในตอนนั้น Hanami ไม่สามารถใช้งานร่วมกับอัญมณี dry-rb เวอร์ชันล่าสุดได้ กล่าวคือ Hanami เวอร์ชันล่าสุดในขณะนั้น (1.3.1) รองรับเฉพาะการตรวจสอบความถูกต้องแบบแห้ง 0.12 เท่านั้นและเราต้องการการตรวจสอบความถูกต้องแบบแห้ง 1.0.0 เราวางแผนที่จะใช้สัญญาจากการตรวจสอบความถูกต้องแบบแห้งซึ่งเปิดตัวใน 1.0.0 เท่านั้น
วิธีคอมไพล์ c++11
นอกจากนี้ Kafka 1.2 ยังเข้ากันไม่ได้กับอัญมณีแห้งดังนั้นเราจึงใช้เวอร์ชันที่เก็บของมัน ปัจจุบันเราใช้ 1.3.0.rc1 ซึ่งขึ้นอยู่กับอัญมณีแห้งใหม่ล่าสุด
นอกจากนี้อัญมณีฮานามิยังมีการอ้างอิงมากเกินไปซึ่งเราไม่ได้วางแผนที่จะใช้เช่น hanami-cli
, hanami-assets
, hanami-mailer
, hanami-view
และแม้กระทั่ง hanami-controller
. นอกจากนี้ดูที่ไฟล์ hanami-model readme เห็นได้ชัดว่ารองรับฐานข้อมูลเดียวโดยค่าเริ่มต้น ในทางกลับกัน ROM.rb ซึ่ง hanami-model
ขึ้นอยู่กับรองรับการกำหนดค่าฐานข้อมูลแบบหลายฐานข้อมูลนอกกรอบ
สรุปแล้วฮานามิโดยทั่วไปและ hanami-model
โดยเฉพาะดูเหมือนระดับนามธรรมที่ไม่จำเป็น
ดังนั้น 10 วันหลังจากที่เราทำการประชาสัมพันธ์ครั้งแรกที่มีความหมายกับ Chronicles เราจึงแทนที่ฮานามิด้วยซินาตร้าทั้งหมด เราสามารถใช้ Pure Rack ได้เช่นกันเพราะเราไม่ต้องการการกำหนดเส้นทางที่ซับซ้อน (เรามีจุดสิ้นสุด 'แบบคงที่' สี่จุด - ปลายทาง GraphQL สองจุดปลายทาง / ping และอินเทอร์เฟซของเว็บไซด์คิค) แต่เราตัดสินใจที่จะไม่ยอมใครง่ายๆเกินไป Sinatra เหมาะกับเราดี หากคุณต้องการเรียนรู้เพิ่มเติมโปรดดูของเรา บทช่วยสอนซินาตร้าและภาคต่อ .
เราใช้เวลาพอสมควรและลองผิดลองถูกมากมายเพื่อหาวิธี 'ปรุงอาหาร' แบบ dry-validation อย่างถูกต้อง
params do required(:url).filled(:string) end params do required(:url).value(:string) end params do optional(:url).value(:string?) end params do optional(:url).filled(Types::String) end params do optional(:url).filled(Types::Coercible::String) end
ในตัวอย่างข้อมูลด้านบน url
พารามิเตอร์ถูกกำหนดด้วยวิธีที่แตกต่างกันเล็กน้อย คำจำกัดความบางคำเทียบเท่ากันและคำจำกัดความอื่น ๆ ก็ไม่สมเหตุสมผล ในตอนแรกเราไม่สามารถบอกความแตกต่างระหว่างคำจำกัดความทั้งหมดได้อย่างแท้จริงเนื่องจากเรายังไม่เข้าใจอย่างถ่องแท้ เป็นผลให้สัญญาเวอร์ชันแรกของเราค่อนข้างยุ่งเหยิง เมื่อเวลาผ่านไปเราได้เรียนรู้วิธีการอ่านและเขียนสัญญา DRY อย่างถูกต้องและตอนนี้มันดูสม่ำเสมอและสง่างาม - อันที่จริงแล้วไม่เพียง แต่สง่างามเท่านั้น แต่ก็ไม่ได้สวยงามอะไรเลย เรายังตรวจสอบการกำหนดค่าแอปพลิเคชันด้วยสัญญา
ROM.rb และ ภาคต่อ แตกต่างจาก ActiveRecord ไม่แปลกใจเลย แนวคิดเริ่มต้นของเราที่ว่าเราจะสามารถคัดลอกและวางโค้ดส่วนใหญ่จากแพลตฟอร์มล้มเหลว ปัญหาคือส่วนของแพลตฟอร์มนั้นหนักมากดังนั้นเกือบทุกอย่างจะต้องถูกเขียนใหม่ใน ROM / Sequel เราจัดการเพื่อคัดลอกโค้ดเพียงส่วนเล็ก ๆ ซึ่งไม่ขึ้นกับกรอบ ระหว่างทางเราประสบปัญหาที่น่าหงุดหงิดและข้อบกพร่องบางประการ
ตัวอย่างเช่นฉันใช้เวลาหลายชั่วโมงในการหาวิธีสร้างแบบสอบถามย่อยใน ROM.rb / Sequel นี่คือสิ่งที่ฉันจะเขียนโดยไม่ต้องตื่นขึ้นมาใน Rails: scope.where(sequence_code: subquery
) แม้ว่าในภาคต่อจะกลายเป็น ไม่ใช่เรื่องง่าย .
def apply_subquery_filter(base_query, params) subquery = as_subquery(build_subquery(params)) base_query.where { Sequel.lit('sequence_code IN ?', subquery) } end # This is a fixed version of https://github.com/rom-rb/rom-sql/blob/6fa344d7022b5cc9ad8e0d026448a32ca5b37f12/lib/rom/sql/relation/reading.rb#L998 # The original version has `unorder` on the subquery. # The fix was merged: https://github.com/rom-rb/rom-sql/pull/342. def as_subquery(relation) attr = relation.schema.to_a[0] subquery = relation.schema.project(attr).call(relation).dataset ROM::SQL::Attribute[attr.type].meta(sql_expr: subquery) end
ดังนั้นแทนที่จะใช้ซับเดียวแบบธรรมดาอย่าง base_query.where(sequence_code: bild_subquery(params))
เราต้องมีโหลบรรทัดที่มีโค้ดที่ไม่สำคัญชิ้นส่วน SQL ดิบและความคิดเห็นหลายบรรทัดเพื่ออธิบายสิ่งที่ทำให้เกิดการขยายตัวที่โชคร้ายนี้
entry
ความสัมพันธ์ (performed_actions
ตาราง) มีหลัก id
ฟิลด์ อย่างไรก็ตามในการเข้าร่วมกับ *taggings
ตารางจะใช้ sequence_code
คอลัมน์. ใน ActiveRecord จะแสดงออกค่อนข้างง่าย:
โมเดลวัตถุหน้าคืออะไร
class PerformedAction เป็นไปได้ที่จะเขียนสิ่งเดียวกันใน ROM ด้วย
module Chronicles::Persistence::Relations::Entries มีปัญหาเล็กน้อยกับมัน มันจะคอมไพล์ได้ดี แต่ล้มเหลวในรันไทม์เมื่อคุณพยายามใช้งานจริง
[4] pry(main)> Chronicles::Persistence.relations[:platform][:entries].join(:access_taggings).limit(1).to_a E, [2019-09-05T15:54:16.706292 #20153] ERROR -- : PG::UndefinedFunction: ERROR: operator does not exist: integer = uuid LINE 1: ...ion_access_taggings' ON ('performed_actions'.'id' = 'perform... ^ HINT: No operator matches the given name and argument types. You might need to add explicit type casts.: SELECT FROM 'performed_actions' INNER JOIN 'performed_action_access_taggings' ON ('performed_actions'.'id' = 'performed_action_access_taggings'.'performed_action_sequence_code') ORDER BY 'performed_actions'.'id' LIMIT 1 Sequel::DatabaseError: PG::UndefinedFunction: ERROR: operator does not exist: integer = uuid LINE 1: ...ion_access_taggings' ON ('performed_actions'.'id' = 'perform...
เราโชคดีที่ประเภทของรหัสและ sequence_code
แตกต่างกันดังนั้น PG จึงแสดงข้อผิดพลาดประเภท ถ้าประเภทเหมือนกันใครจะรู้ว่าฉันจะใช้เวลาแก้ไขข้อบกพร่องนี้กี่ชั่วโมง
ดังนั้น entries.join(:access_taggings)
ไม่ทำงาน จะเกิดอะไรขึ้นถ้าเราระบุเงื่อนไขการเข้าร่วมอย่างชัดเจน? เช่นเดียวกับ entries.join(:access_taggings, performed_action_sequence_code: :sequence_code)
ตามที่เอกสารอย่างเป็นทางการแนะนำ
[8] pry(main)> Chronicles::Persistence.relations[:platform][:entries].join(:access_taggings, performed_action_sequence_code: :sequence_code).limit(1).to_a E, [2019-09-05T16:02:16.952972 #20153] ERROR -- : PG::UndefinedTable: ERROR: relation 'access_taggings' does not exist LINE 1: ....'updated_at' FROM 'performed_actions' INNER JOIN 'access_ta... ^: SELECT FROM 'performed_actions' INNER JOIN 'access_taggings' ON ('access_taggings'.'performed_action_sequence_code' = 'performed_actions'.'sequence_code') ORDER BY 'performed_actions'.'id' LIMIT 1 Sequel::DatabaseError: PG::UndefinedTable: ERROR: relation 'access_taggings' does not exist
ตอนนี้มันคิดว่า :access_taggings
เป็นชื่อตารางด้วยเหตุผลบางประการ ได้เลยลองสลับกับชื่อตารางจริง
[10] pry(main)> data = Chronicles::Persistence.relations[:platform][:entries].join(:performed_action_access_taggings, performed_action_sequence_code: :sequence_code).limit(1).to_a => [#]
ในที่สุดมันก็ส่งคืนบางสิ่งและไม่ล้มเหลวแม้ว่ามันจะจบลงด้วยนามธรรมที่รั่วไหล ชื่อตารางไม่ควรรั่วไหลไปยังรหัสแอปพลิเคชัน
การแก้ไขพารามิเตอร์ SQL
มีคุณลักษณะในการค้นหา Chronicles ซึ่งช่วยให้ผู้ใช้สามารถค้นหาโดย payload แบบสอบถามมีลักษณะดังนี้ {operation: :EQ, path: ['flag', 'gid'], value: 'gid://plat/Flag/1'}
โดยที่ path
เป็นอาร์เรย์ของสตริงเสมอและค่าคือค่า JSON ที่ถูกต้อง
ใน ActiveRecord ดูเหมือนว่า นี้ :
@scope.where('payload -> :path #> :value::jsonb', path: path, value: value.to_json)
ในภาคต่อฉันไม่สามารถแก้ไข :path
ได้อย่างถูกต้องดังนั้นฉันจึงต้องหันไปใช้ ที่ :
base_query.where(Sequel.lit('payload #> '{#{path.join(',')}}' = ?::jsonb', value.to_json))
โชคดีที่ path
ที่นี่ได้รับการตรวจสอบอย่างถูกต้องเพื่อให้มีเฉพาะอักขระที่เป็นตัวเลขและตัวอักษร แต่รหัสนี้ยังดูตลก
Silent Magic ของ ROM-factory
เราใช้ไฟล์ rom-factory
อัญมณีเพื่อลดความซับซ้อนในการสร้างแบบจำลองของเราในการทดสอบ อย่างไรก็ตามหลายครั้งรหัสไม่ทำงานตามที่คาดไว้ คุณเดาได้ไหมว่าการทดสอบนี้มีอะไรผิดพลาด?
[:] ใน python
action1 = RomFactory[:action, app: 'plat', subject_type: 'Job', action: 'deleted'] action2 = RomFactory[:action, app: 'plat', subject_type: 'Job', action: 'updated'] expect(action1.id).not_to eq(action2.id)
ไม่ความคาดหวังไม่ล้มเหลวความคาดหวังนั้นดี
ปัญหาคือบรรทัดที่สองล้มเหลวโดยมีข้อผิดพลาดในการตรวจสอบข้อ จำกัด เฉพาะ เหตุผลก็คือ action
ไม่ใช่แอตทริบิวต์ที่ Action
มีโมเดล ชื่อจริงคือ action_name
ดังนั้นวิธีที่ถูกต้องในการสร้างการกระทำควรมีลักษณะดังนี้:
RomFactory[:action, app: 'plat', subject_type: 'Job', action_name: 'deleted']
เนื่องจากแอตทริบิวต์ที่พิมพ์ผิดถูกละเว้นจึงกลับไปเป็นค่าเริ่มต้นที่ระบุไว้ในโรงงาน (action_name { 'created' }
) และเรามีการละเมิดข้อ จำกัด ที่ไม่ซ้ำกันเนื่องจากเราพยายามสร้างการกระทำที่เหมือนกันสองรายการ เราต้องจัดการกับปัญหานี้หลายครั้งซึ่งพิสูจน์แล้วว่าต้องเสียภาษี
โชคดีที่มันเป็น แก้ไขแล้ว ใน 0.9.0 Dependabot ส่งคำขอดึงข้อมูลโดยอัตโนมัติพร้อมกับการอัปเดตไลบรารีซึ่งเรารวมเข้าด้วยกันหลังจากแก้ไขแอตทริบิวต์ที่พิมพ์ผิดสองสามรายการที่เรามีในการทดสอบของเรา
การยศาสตร์ทั่วไป
สิ่งนี้กล่าวได้ทั้งหมด:
# ActiveRecord PerformedAction.count _# => 30232445_ # ROM EntryRepository.new.root.count _# => 30232445_
และความแตกต่างนั้นยิ่งใหญ่กว่าในตัวอย่างที่ซับซ้อนมากขึ้น
ส่วนที่ดี
ไม่ใช่ความเจ็บปวดหยาดเหงื่อและน้ำตาทั้งหมด มีหลายสิ่งที่ดีมากมายในการเดินทางของเราและพวกเขาก็มีมากกว่าแง่ลบของกองถ่ายใหม่ หากไม่เป็นเช่นนั้นเราคงไม่ทำตั้งแต่แรก
ทดสอบความเร็ว
ใช้เวลา 5-10 วินาทีในการรันชุดทดสอบทั้งหมดในเครื่องและนานสำหรับ RuboCop เวลา CI นานกว่ามาก (3-4 นาที) แต่นี่เป็นปัญหาน้อยกว่าเพราะเราสามารถเรียกใช้ทุกอย่างในเครื่องได้ด้วยเหตุนี้สิ่งที่ล้มเหลวใน CI จึงมีโอกาสน้อยกว่ามาก
อัญมณียาม กลับมาใช้งานได้อีกครั้ง ลองนึกภาพว่าคุณสามารถเขียนโค้ดและเรียกใช้การทดสอบในการบันทึกแต่ละครั้งได้ซึ่งจะให้ข้อเสนอแนะที่รวดเร็วมาก นี่เป็นเรื่องยากที่จะจินตนาการได้เมื่อทำงานกับแพลตฟอร์ม
ปรับใช้เวลา
เวลาในการปรับใช้แอป Chronicles ที่แยกออกมาคือเพียงสองนาที ไม่เร็วปานสายฟ้า แต่ก็ยังไม่แย่ เราปรับใช้บ่อยมากดังนั้นแม้แต่การปรับปรุงเล็กน้อยก็สามารถช่วยประหยัดได้มาก
ประสิทธิภาพการใช้งาน
ส่วนที่เน้นประสิทธิภาพมากที่สุดของ Chronicles คือการค้นหารายการ ตอนนี้มีสถานที่ประมาณ 20 แห่งในส่วนหลังของแพลตฟอร์มที่ดึงรายการประวัติจาก Chronicles ซึ่งหมายความว่าเวลาตอบสนองของ Chronicles มีส่วนช่วยในงบประมาณ 60 วินาทีของแพลตฟอร์มสำหรับเวลาตอบสนองดังนั้น Chronicles จึงต้องรวดเร็วซึ่งก็คือ
แม้จะมีขนาดใหญ่ของบันทึกการดำเนินการ (30 ล้านแถวและเพิ่มขึ้นเรื่อย ๆ ) แต่เวลาตอบกลับโดยเฉลี่ยน้อยกว่า 100 มิลลิวินาที ดูแผนภูมิที่สวยงามนี้:

โดยเฉลี่ย 80-90% ของเวลาแอปจะใช้ในฐานข้อมูล นั่นคือสิ่งที่แผนภูมิประสิทธิภาพที่เหมาะสมควรมีลักษณะดังนี้
เรายังคงมีข้อความค้นหาที่ช้าซึ่งอาจใช้เวลาหลายสิบวินาที แต่เรามีแผนที่จะกำจัดมันออกไปแล้วเพื่อให้แอปที่แยกออกมานั้นเร็วยิ่งขึ้น
โครงสร้าง
สำหรับวัตถุประสงค์ของเรา การตรวจสอบความแห้ง เป็นเครื่องมือที่มีประสิทธิภาพและยืดหยุ่นมาก เราส่งผ่านข้อมูลทั้งหมดจากโลกภายนอกผ่านสัญญาและทำให้เรามั่นใจได้ว่าพารามิเตอร์อินพุตนั้นมีรูปแบบที่ดีและเป็นประเภทที่กำหนดไว้อย่างดีเสมอ
ไม่จำเป็นต้องโทรอีกต่อไป .to_s.to_sym.to_i
ในรหัสแอปพลิเคชันเนื่องจากข้อมูลทั้งหมดถูกล้างและพิมพ์ที่ขอบของแอป ในแง่หนึ่งมันนำความมีจิตใจที่แข็งแกร่งมาสู่โลก Ruby ที่ไม่หยุดนิ่ง ฉันไม่สามารถแนะนำได้เพียงพอ
คำพูดสุดท้าย
การเลือกกองที่ไม่ได้มาตรฐานนั้นไม่ตรงไปตรงมาอย่างที่เห็นในตอนแรก เราพิจารณาหลายแง่มุมเมื่อเลือกเฟรมเวิร์กและไลบรารีที่จะใช้สำหรับบริการใหม่: กลุ่มเทคโนโลยีปัจจุบันของแอปพลิเคชันเสาหินความคุ้นเคยของทีมกับสแต็กใหม่วิธีดูแลสแต็กที่เลือกไว้และอื่น ๆ
แม้ว่าเราจะพยายามตัดสินใจอย่างรอบคอบและคำนวณตั้งแต่ต้น - เราเลือกใช้กองซ้อนฮานามิมาตรฐาน - เราต้องพิจารณาสแต็กของเราใหม่ตลอดทางเนื่องจากข้อกำหนดทางเทคนิคที่ไม่ได้มาตรฐานของโครงการ เราลงเอยด้วย Sinatra และสแต็คแบบแห้ง
เราจะเลือก Hanami อีกครั้งหรือไม่ถ้าเราจะแยกแอปใหม่ อาจจะใช่. ตอนนี้เราทราบข้อมูลเพิ่มเติมเกี่ยวกับห้องสมุดและข้อดีข้อเสียเพื่อให้เราสามารถตัดสินใจได้อย่างมีข้อมูลมากขึ้นตั้งแต่เริ่มโครงการใหม่ ๆ อย่างไรก็ตามเราจะพิจารณาใช้แอป Sinatra / DRY.rb ธรรมดาอย่างจริงจัง
สรุปแล้วเวลาที่ลงทุนไปกับการเรียนรู้กรอบรูปแบบใหม่กระบวนทัศน์หรือภาษาโปรแกรมทำให้เรามีมุมมองใหม่ ๆ เกี่ยวกับกองเทคโนโลยีปัจจุบันของเรา เป็นเรื่องดีเสมอที่จะทราบว่ามีอะไรอยู่บ้างเพื่อเพิ่มคุณค่าให้กล่องเครื่องมือของคุณ เครื่องมือแต่ละชิ้นมีกรณีการใช้งานที่แตกต่างกันดังนั้นการทำความรู้จักกับเครื่องมือเหล่านี้ให้ดีขึ้นหมายถึงการมีเครื่องมือเหล่านี้ให้คุณใช้งานได้มากขึ้นและเปลี่ยนให้เหมาะกับการใช้งานของคุณมากขึ้น
ทำความเข้าใจพื้นฐาน
Tech Stack คืออะไร?
Tech Stack คือชุดเครื่องมือภาษาโปรแกรมรูปแบบสถาปัตยกรรมและโปรโตคอลการสื่อสารที่ทีมปฏิบัติตามเมื่อพัฒนาแอปพลิเคชัน
เหตุใดสัดส่วนจึงสำคัญในการออกแบบ
คุณจะเลือกกองเทคโนโลยีสำหรับการพัฒนาเว็บแอปพลิเคชันได้อย่างไร?
ในการเลือกกองเทคโนโลยีสำหรับการพัฒนาเว็บแอปพลิเคชันจำเป็นต้องคำนึงถึงปัจจัยหลายอย่างรวมถึงความคุ้นเคยของทีมพัฒนากับสแต็กเทคโนโลยีความเหมาะสมของสแต็กกับข้อกำหนดด้านการทำงานของแอปพลิเคชันและความสามารถในการบำรุงรักษาในระยะยาวของโซลูชันที่สร้างขึ้น กับกองที่เลือก
กองเทคโนโลยีขององค์กรปัจจุบันของคุณคืออะไร?
กลุ่มเทคโนโลยีของเราอาศัย Ruby ที่ส่วนหลังในขณะที่ส่วนหน้าเราใช้ React และ typescript ส่วนหน้าสื่อสารกับส่วนหลังผ่าน GraphQL และบางครั้งโปรโตคอล REST การสื่อสารแบบอะซิงโครนัสของบริการส่วนหลังเกิดขึ้นผ่าน Kafka หรือซิงโครนัสโดยใช้ GraphQL / REST เราใช้ PostgreSQL และ Redis เป็นฐานข้อมูลของเรา