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

C++ : OOP 아닌 다른 대안은 없을까?

kakao
November 01, 2024

C++ : OOP 아닌 다른 대안은 없을까?

#C++ #OOP #개발방법론

C++ 언어 사용자로서 수십년간 당연시하게 여겨온 OOP 방법론에 대해서 현실을 돌아보고, OOP 고통을 벗어나게 해 줄 방법들, 특히 최근 여러 컨퍼런스에서 주목받았던 value oriented programming에 대해서 살펴보고, 현실적으로 이를 적용할 immutable data structure에 대해서 살펴본다.

발표자 : heath.hekim
C++로 카카오톡을 개발하고 있습니다.

kakao

November 01, 2024
Tweet

More Decks by kakao

Other Decks in Programming

Transcript

  1.  ؀୓۽ $ ঱য੄ Үਭ਷ 001ѐ֛ਸ ࣗѐೞח Ѫਵ۽ द੘ 

    Үਭ җ੿ীࢲ ੗োझۣѱ $ ঱যܳ 001ߑधਵ۽ ׮ܖח Ѫࠗఠ Үਭ  ୡ߈ী ߓ਋ח ղਊਵ۽ DMBTT WJSUVBMఃਕ٘৬ ࢚ࣘী ҙೠ ղਊٜ $ Үਭ੄ द੘
  2.  ঱যܳ ߓ਋Ҋ पޖীࢲ ੽ೞח ৈ۞ GSBNFXPSL ৉द ؀ࠗ࠙ 001ಁఢ

    ӝ߈  .'$ 25 $0. .77. j  ੊ࣼೠ ಁఢਸ ߓ਋Ҋ ࢎਊೞҊ ࣄ೐ ъച Ҋ଱ച  $ ঱যܳ ࢎਊೞݶࢲ 001੉৻੄ ߑधਸ ځৢܻӝ য۰਑ $ ҃۱੄ द੘  IUUQTMFBSONJDSPTPGUDPNFOVTDQQNGDIJFSBSDIZDIBSU WJFXNTWD 1)
  3.  $ ঱যח ׮নೠ ಁ۞׮੐ਸ ૑ਗೞ૑݅ 001 ѐߊ੉ о੢ ؀઺੸

     001੄ ౠ૚ ஭ङച࢚ࣘ׮ഋࢿ୶࢚ച  ஭ङച ࠂ੟ೠ ղࠗ ࢚కܳ ऀӣ  ࢚ࣘ ӝઓ ௿ېझܳ ഛ੢ೞৈ ੤ࢎਊ  ׮ഋࢿ ೞա੄ ੋఠಕ੉झ۽ ৈ۞ ӝמਸ ࢎਊ  ୶࢚ച ࠂ੟ೠ दझమਸ рױೞѱ ݽ؛݂ 001ࠂणೞӝ
  4.  001о ਬܻೠ ѐߊ ࠙ঠо ੓ਸө  (6*৬ FWFOUESJWFOQSPHSBNNJOH 

    ۄ੉࠳۞ܻ ѐߊী ਬܻ  അप ࣁ҅ܳ ݽ؛݂ ೞחؘ ਬਊ 001੢੼
  5.  ஭ङച ࠂ੟ೠ ղࠗ ࢚కܳ ऀӣ   ௏٘ܳ ੉೧ೞӝ

    য۵ѱ ٜ݅ ࣻ ੓਺  ੜ ஭ङച ػ ௏٘ܳ ࢎਊೞח Ѫҗ ѐߊ ߂ ਬ૑ࠁࣻ ೞח Ѫ੄ рӓ 001஭ङച੄ য۰਍ ੼
  6.  ࢚ࣘ਷ о੢ ъ۱ೠ ழ೒݂  *OIFSJUBODFױ҅о Өয૑Ҋ ѐ߹ ё୓੄

    ৉ೡ੉ ݽഐ೧ ૑ݶ ഒۆ੉ ழ૗  #BDLUP#BTJDT0CKFDU0SJFOUFE1SPHSBNNJOH +PO,BMC $QQ$PO જ਷ ৘ 001࢚ࣘ੄ য۰਍ ੼
  7. 001࢚ࣘਸ য۵ѱ ݅٘ח ৘ class CAnimal { public: virtual void

    move() const { ... } virtual ~CAnimal() = default; }; class CBird : public CAnimal { public: void move() const override { … } }; class CMammal : public CAnimal { public: void move() const override { if (isFlyingMammal) { std::cout << "Mammal flies like a bat." << std::endl; } else { std::cout << "Mammal walks." << std::endl; } } void setFlyingMammal(bool canFly) { isFlyingMammal = canFly; } private: bool isFlyingMammal = false; // New requirement forces extra logic into CMammal }; class CFlyingMammal : public CMammal { public: CFlyingMammal() { setFlyingMammal(true); } void move() const override { std::cout << "Flying mammal glides through the air." << std::endl; CMammal::move(); } };
  8.  ୶࢚ച ػ ё୓ܳ оܻఃח ਊযח ࢎۈ݃׮ ׮ܲ Ѫਸ ځৢܻӝ

    ए਑ NFOUBMNPEFM  ੉ܴਸ ੜ ૑ਵ۰ח ֢۱੉ ೙ਃ 001୶࢚ച੄ য۰਑ DPOUFYU
  9.  ௏٘ ੤ࢎਊਸ ਤ೧ ࢚ࣘਸ ഝਊೞҊ ࠗݽ ௿ېझীࢲ ࠙ӝо ࢤӣ

     4JOHMFUPOҗ .BOBHFSо ࢤӝӝ द੘  ߄۽ ੉೧غ૑ ঋח ҳઑ NPEFM ٜ੉ ١੢  ୶࢚ച ߂ ੌ߈ചܳ ਤ೧ औѱ ੉೧ೡ ࣻ হѢա ਬ૑ࠁࣻ ೞӝ য۰਍ ӝٜࣿ੉ ੸ਊؽ 001੉࢚җ അप
  10.  001ח PCKFDUٜ р੄ rҙ҅sܳ ࢤࢿೣ  0CKFDU ࢎ੉ীࢲ੄ ҙ҅ח

    r৊੐sਸ ݅ٚ׮  4JEFFGGFDU OPOMPDBMSFBTPOJOHߊࢤ  <୶ୌ>5POZ7BO&FSE WBMVFPSJFOUFEQSPHSBNNJOHҙ۲ UBMLT 001 য۰਍ ੉ਬח ޖ঺ੌө
  11.  001ܳ ੜ ॳח ߑߨٜী ؀ೠ ৈ۞ о੉٘о ੓णפ׮ 

    JTBҙ҅ੌٸ݅ ࢲ࠳ ఋੑੌٸ݅ ࢚ࣘਸ ࢎਊ  /POMFBG௿ېझח BCTUSBDUDMBTT۽ ੘ࢿ  ࢚ࣘࠁ׮ח DPNQPTJUJPOਸ ࢎਊ  $ ঱যীࢲ੄ ب਑DPOTU GJOBM PWFSSJEF QVSFWJSUVBMGVODUJPO 001ੜ ࢎਊೞӝ ਤೠ ֢۱ٜ
  12.  ࠛ߸ࢿ JNNVUBCJMJUZ WTо߸ࢿ NVUBCJMJUZ  ؀಴੸ੋ ৘ JOU $ķŖŐŕś

    WT$ľJEHFU DMBTT  ز੘ߑध੄ ର੉ QVSFGVODUJPOWT ࢎ੉٘ ੉ಖ౟  Ӓ ৻ ର੉੼ٜ ध߹ࢿ *EFOUJUZ DPQZز੘ߑध 7BMVF৬ 0CKFDU
  13.  ч ઺ब੄ ೐۽Ӓې߁  .VUBCMF0CKFDUࠁױ *NNVUBCMFWBMVFUZQF઺बਵ۽ ѐߊ  5SBOTGPSNBUJPOPGEBUB

    OPUNVUBUJPOPGTUBUF  *OIFSJUBODFࠁ׮ח DPNQPTJOHࢎਊ  1VSFGVODUJPO TJEFFGGFDUо হח ೣࣻ ੸ӓ ࢎਊ  4UBUF EBUB ৬ CFIBWJPSܳ ܻ࠙ 7BMVFPSJFOUFEQSPHSBNNJOHࣗѐ
  14. WBMVFPSJFOUFE੸ਊ ৘   1VSFGVODUJPOWTSFGFSFODF // reference void addToVector(std::vector<int>& vec,

    int value) { vec.push_back(value); } // Value-oriented std::vector<int> addToVector(const std::vector<int>& vec, int value) { auto result = vec; result.push_back(value); return result; }
  15. WBMVFPSJFOUFE੸ਊ ৘   *NNVUBCMFEBUBTUSVDUVSF // std::string (mutable) std::string s

    = "Hello"; s += " World"; // s 를 수정 // immutable string type immutable_string s = "Hello"; auto new_s = s + " World"; // 새로운 string 생성, s는 변하지 않음
  16. WBMVFPSJFOUFE੸ਊ ৘   BDUJPOীࢲ DBMDVMBUJPOਸ ܻ࠙ TJEFFGGFDUܳ ઁѢ //

    Not value-oriented void processOrder(Order& order) { double total = calculateTotal(order); order.setTotal(total); sendConfirmationEmail(order); } // Value-oriented struct ProcessedOrder { Order order; double total; }; ProcessedOrder calculateProcessedOrder(const Order& order) { return {order, calculateTotal(order)}; } void handleOrder(const ProcessedOrder& processedOrder) { sendConfirmationEmail(processedOrder); }
  17. WBMVFPSJFOUFE੸ਊ ৘   TUEPQUJPOBM5ա TUEWBSJBOU5ࢎਊ // Not value-oriented bool

    parseInteger(const std::string& s, int& result) { try { result = std::stoi(s); return true; } catch (...) { return false; } } // Value-oriented std::optional<int> parseInteger(const std::string& s) { try { return std::stoi(s); } catch (...) { return std::nullopt; } }
  18.  TUETPSU TUEGJOE TUEUSBOTGPSNҗ э਷ HFOFSJDBMHPSJUINTWBMVFӝ߈ਵ۽ ز੘  ঌҊ્ܻҗ ؘ੉ఠ੄

    ܻ࠙  *UFSBUPS ஶప੉ց੄ TUBUFܳ ׮ܖ૑ ঋ਺ $ ಴ળ ۄ੉࠳۞ܻ৬ 7BMVFPSJFOUFEਗ஗ std::vector<int> input = {1, 2, 3, 4, 5}; std::vector<int> output(input.size()); std::transform(input.begin(), input.end(), output.begin(), [](int i) { return i * i; });
  19.  $ ੄ ӝמٜ  TUEWBSJBOU TUEPQUJPOBM TUEFYQFDUFE 701ҳഅ ஏݶীࢲ

    $ ೖ୊ٜ // Not value-oriented class Shape { public: virtual double area() = 0; }; class Circle : public Shape { double radius; public: double area() override { return 3.14159 * radius * radius; } }; class Rectangle : public Shape { double width, height; public: double area() override { return width * height; } }; // Value-oriented struct Circle { double radius; }; struct Rectangle { double width; double height; }; using Shape = std::variant<Circle, Rectangle>; double area(const Shape& shape) { return std::visit([](const auto& s) { using T = std::decay_t<decltype(s)>; if constexpr (std::is_same_v<T, Circle>) return 3.14159 * s.radius * s.radius; else if constexpr (std::is_same_v<T, Rectangle>) return s.width * s.height; }, shape); }
  20.  -BHFS +VBOQF #PM䠃WBS  IUUQTHJUIVCDPNBSYJNCPMEJMBHFS  6OJEJSFDUJPOBMEBUBGMPXBSDIJUFDUVSF  $

    ਸ ਤೠ 3FEVY  TUPSFSFEVDFSBDUJPOFGGFDU 701ܳ ਤೠ MJCSBSZࣗѐ MBHFS  IUUQTXXXZPVUVCFDPNXBUDI W@P#Y@/C-HI: 2)
  21.  4UBUF৬ BMHPSJUIN੄ ܻ࠙  .PEFMTUBUF  3FEVDFSBMHPSJUIN  "DUJPOਸ

    ా೧ࢲ݅ SFEVDFSഐ୹  3FEVDFSܳ ా೧ࢲ݅ NPEFMਸ USBOTGPSNBUJPO  .PEFM੄ ߸҃ਸ х૑ೡ ࣻ ੓ח ӝמ ઁҕ 701ܳ ਤೠ MJCSBSZࣗѐ MBHFS  IUUQTTJOVTPJEFTMBHFSBSDIJUFDUVSFIUNM 3)
  22. struct model { int value = 0; }; struct increment_action

    {}; struct decrement_action {}; struct reset_action { int new_value = 0; }; using action = std::variant<increment_action, decrement_action, reset_action>; auto store = lager::make_store<counter::action>( counter::model{}, lager::with_manual_event_loop{}); -BHFS௏٘ ৘ઁ  IUUQTTJOVTPJEFTMBHFSBSDIJUFDUVSFIUNM 1)
  23. model update(model c, action action) { return std::visit(lager::visitor{ [&](increment_action) {

    ++ c.value; return c; }, [&](decrement_action) { -- c.value; return c; }, [&](reset_action a) { c.value = a.new_value; return c; }, }, action); } : : : : : : store.dispatch(increment_action{});  IUUQTTJOVTPJEFTMBHFSBSDIJUFDUVSFIUNM
  24. void draw(counter::model curr) { std::cout << "current value: " <<

    curr.value << '\n'; } watch(store, draw);  IUUQTTJOVTPJEFTMBHFSBSDIJUFDUVSFIUNM
  25.  $VSTPSNPEFM੄ XSBQQFS NPEFMDIBOHFEDBMMCBDL [PPNઁҕ  -FOTNPEFM ੹୓ীࢲ ੌࠗܳ WJFXTFUೞח

    ೣࣻ੄ ૘೤ -BHFS੄ ୶о ӝמٜ struct room{ bool light = false; }; struct house { std::map<string, room> rooms; }; auto store = lager::make_store<house_action>( initial_house, lager::with_manual_event_loop{}); lager::reader<room> kitchen_cursor = store .zoom(lager::lenses::attr(&house::rooms)) .zoom(lager::lenses::at("kitchen"));  IUUQTTJOVTPJEFTMBHFSDVSTPSTIUNM 4)
  26. store.dispatch(change_room_action{"kitchen", toogle_light_action{}}); using house_action = std::variant<change_room_action, add_room_action>; house update(house h,

    house_action a) { return std::visit(lager::visitor{ [&](change_room_action a) { auto old_room = h.rooms[a.id]; auto new_room = room {!old_room.light_on}; h.rooms[a.id] = new_room; return h; }, [&](add_room_action a) { h.rooms[a.id] = a.r; return h; } }, a); }  IUUQTTJOVTPJEFTMBHFSDVSTPSTIUNM
  27.  7BMVFӒܻҊ DPQZ  $POUBJOFS੄ DPQZޙઁ  $POUBJOFS੄ VQEBUFޙઁ 

    ബਯ੸ੋ JNNVUBCMFEBUBTUSVDUVSF೙ਃࢿ 7BMVFTFNBOUJDTܳ о۽݄ח Ѫ struct model { std::vector<char> some_huge_vec; }; model update(model m, action a) { auto new_model = model {m. some_huge_vec[a.index]++}; return new_model; }
  28.  $ *NNVUBCMFؘ੉ఠ ҳઑ  ݽٚ ݫࣗ٘о DPOTU  ߸҃غח

    ൤झషܻܳ ਬ૑ EJGGࣻ೯ оמ  ߸҃غ૑ ঋח ؘ੉ఠח ղࠗ ҕਬ DPQZ୭ࣗച *NNVUBCMFEBUBTUSVDUVSF JNNFS const auto v0 = vector<int>{}; const auto v1 = v0.push_back(15); const auto v2 = v1.push_back(16); const auto v3 = v2.set(0, 42); assert(v2.size() == v0.size() + 2); assert(v3[0] - v1[0] == 27);  IUUQTTJOVTPJEFTUBMLTJNNFSDQQDPO 5)
  29.  ബਯ੸ੋ EJGG .PEFM߸҃ ఐ૑ ӝמ struct model { immer::map<int,

    string> value; }; model m1 { {1, “1”}}; auto m2 = model{ m1.set(1, “one”) }; auto added = [](auto x){}; auto removed = [](auto x){}; auto changed = [](auto x, auto y){}; immer::diff(m1, m2, added, removed, changed);
  30.  -BHFSী ࢎਊغח ݽ؛ਸ JNNFS ۄ੉࠳۞ܻ ࢎਊ೧ࢲ WBMVFఋੑਵ۽ ੘ࢿ -BHFS

    *NNFS struct model { immer::box<data> data1; immer::set<int> integers; immer::map<int, string> m; }; auto store = lager::make_store< model >(model{}, lager::with_manual_event_loop{});
  31. model update(model m, action a) { : : : }

    lager::watch(cursor, [prev_m = cursor.get()](auto new_m){ immer::diff(new_m, prev_m, [](auto added){ add_item(added); }…); refresh_ui();, });
  32.  7BMVFPSJFOUFE1SPHSBNNJOHࣗѐ  001 ߑधਵ۽ ѐߊೞݴ Ҋా߉Ҋ ੓׮ݶ ੌࠗ ੸ਊਸ

    Ҋ۰  -BHFS001৬ 701ܳ োѾ೧઱ח ࠳݁૑  *NNFS701੸ਊਸ ذח ۄ੉࠳۞ܻ ݃஖ݴ
  33. 2"

  34. ଵҊ ޙ೴  .JDSPTPGU r.'$DMBTTIJFSBSDIZDIBSUs IUUQTMFBSONJDSPTPGUDPNFOVTDQQNGDIJFSBSDIZDIBSU WJFXNTWD  $QQ$PO +VBO1FESP#PMJWBS1VFOUFt5IF.PTU7BMVBCMF7BMVFTu

    IUUQTXXXZPVUVCFDPNXBUDI W@P#Y@/C-HI:  +6"/1&%30#0-䟦7"316&/5& -BHFSEPDT IUUQTTJOVTPJEFTMBHFSBSDIJUFDUVSFIUNM  +6"/1&%30#0-䟦7"316&/5& -BHFSEPDT IUUQTTJOVTPJEFTMBHFSDVSTPSTIUNM  +6"/1&%30#0-䟦7"316&/5& -BHFSEPDT IUUQTTJOVTPJEFTUBMLTJNNFSDQQDPO  +6"/1&%30#0-䟦7"316&/5& ֤ޙ t1FSTJTUFODFGPSUIF.BTTFT33#7FDUPSTJOB4ZTUFNT-BOHVBHFu IUUQTQVCMJDTJOVTPJEFTNJTDJNNFSJNNFSJDGQQEG