Breaking Dependencies - The Visitor Design Pattern in Cpp - Klaus Iglberger - CppCon 2022

  Рет қаралды 34,420

CppCon

CppCon

Жыл бұрын

cppcon.org/
---
Breaking Dependencies - The Visitor Design Pattern in C++ - Klaus Iglberger - CppCon 2022
github.com/CppCon/CppCon2022
The extensibility of code with new functionality is essential for long-term maintenance of a code base. However, when using dynamic polymorphism there is always a choice: either easily add types, or easily add operations. For instance, by means of inheritance hierarchies it's easy to add new types, but it's difficult to add new operations.
But there is a common workaround to overcome this weakness: the Visitor design pattern.
In this talk, I’ll explain the design properties of Visitor, including its benefits and shortcomings. I’ll also talk about different kinds of visitors (cyclic and acyclic) and show when to reach for a Visitor and when to avoid it. Additionally, I’ll demonstrate the different implementation strategies (classic and modern) and address their individual benefits and problems.
---
Klaus Iglberger
Klaus Iglberger is a freelance C++ trainer and consultant. He has finished his PhD in Computer Science in 2010 and since then is focused on large-scale C++ software design. He shares his expertise in popular advanced C++ courses around the world (mainly in Germany, but also in the rest of the EU and the US). Additionally, he is the initiator and lead designer of the Blaze C++ math library (bitbucket.org/blaze-lib/blaze/), one of the organizers of the Munich C++ user group (www.meetup.com/MUCplusplus/), and the organizer of the Back-to-Basics track at CppCon.
---
Videos Filmed & Edited by Bash Films: www.BashFilms.com
KZbin Channel Managed by Digital Medium Ltd events.digital-medium.co.uk
#cppcon #programming #cpp

Пікірлер: 38
@StefaNoneD
@StefaNoneD Жыл бұрын
Klaus Iglberger is definitely my favorite presenter!
@russCoding
@russCoding Жыл бұрын
Absolutely amazing presentation! Thank you Klaus Iglberger, I really enjoyed watching this and learned a good few things along the way. Do not hesitate to hire this man for training.
@Barfriedrich12
@Barfriedrich12 Жыл бұрын
In relation to the Acyclic Visitor pattern presented, I believe the Visitor classes could virtually inherit from the empty base AbstractVisitor, and therefore both let operation implementers eschew the extra base and potentially obviate the cross-cast in the accept implementations in favor of a simple downcast. Can anyone shine some light on any downsides? Edit: Oops that’s impossible. Have a nice day people
@salehjamali8752
@salehjamali8752 10 ай бұрын
Enjoyed it, ty for sharing it
@davithov
@davithov 8 ай бұрын
So, visitor is for adding operations and type erasures for adding types easily. What if we combine and apply these two concepts, i.e., apply type erasure on the "visitor" hierarchy part? Or maybe std::variant is doing that?
@davidsicilia5316
@davidsicilia5316 Жыл бұрын
good talk
@theskydebreuil
@theskydebreuil 2 ай бұрын
Nice thanks for the talk. I agree visitor works good in some cases. To be honest though I’ve seen it applied in cases where it makes everything very complex, especially when templates start to become involved. It seems to suffer a bit from the issue where if you make a new class you then need to update like 10 different spots to fully implement it. It ends up being a bit similar to having switch statements everywhere for an enum type. Also the issue where you need to know all the types used in a std::variant beforehand, so can’t extend things from different assemblies without adding a lot of templating. But as always, time and place 😊
@guillermotomasini
@guillermotomasini Жыл бұрын
amazing....
@perfectionbox
@perfectionbox 7 ай бұрын
how does this compare to using components?
@oschonrock
@oschonrock Жыл бұрын
Very good Klaus. Great complement to the type erasure talks. Perhaps would have liked to have seen the overload() idiom for the implementation of the modern visitor, rather than a functor.
@alexeysubbota
@alexeysubbota Жыл бұрын
I don't think recompilation in result of touching (6:50) the enum is a disaster. Making change all over the code is much more important though
@thomasziereis330
@thomasziereis330 6 ай бұрын
looks all nice on paper but i rather debug a switch statement with a type instead of a std::visit on a variant. std::visit looks only good until u actually use it. imo std::visit was a mistake and is just a very very horrible compensation for not having pattern matching
@controlflow89
@controlflow89 Жыл бұрын
No mention of Expression problem… :(
@embeddor3023
@embeddor3023 Жыл бұрын
Since I started working in HPC, whenever I see dynamic polymorphism used on data, I cry inside. I think I need a therapy ...
@ABaumstumpf
@ABaumstumpf Жыл бұрын
Why? It can also make the code easier to read and it can be better performance - just depends on the design.
@embeddor3023
@embeddor3023 Жыл бұрын
@ABaumstumpf 2 simple rules: - if you need indirection, don't pay for it for every data element. Instead of vector, use tuple. This utilizes all the cache lines for the data during iteration. This is suitable for closed polymorphism. - For open polymorphism, use virtual functions that take ARRAYS of elements and not a single element as arguments. This makes the indirection overhead much lower as you need to jump only once for every element type.
@treyquattro
@treyquattro Жыл бұрын
@@embeddor3023 that's a nice example of Structure of Arrays (SoA) versus of Array of Structures (AoS) which was well explained in Avi Lachmish's CppCon 22 presentation on data locality and parallelism
@phusicus_404
@phusicus_404 Ай бұрын
Is variant indirection? It stores data in place ​@@embeddor3023
@davithov
@davithov 2 ай бұрын
Author says that with the visitor pattern it is easier to add operations․ My concern is that actually, instead of overriding those functions in derived classes, we create types of these functions (like Rotate, Draw etc.) and when we add a function, we need to introduce new type like, e.g., Serialize. But this is not enough actually: we have to also override ALL visit functions in that class. So, what is the difference between overriding visit functions and Serialize function in a derived classes? In any case in both cases we have to override K functions (either visit or a function) if there are K operations. Although I understand that we actually might break dependencies from 3rd parties in our actual concrete class (like Circle, Square etc.). For example, if there is a 3rd party tool which helps to draw, then Circle won't know anything about that library. Instead, concrete visitor will know about it, hence we avoid introducing dependencies from 3rd party library for the concrete types (Shapes). I mean this is I understand and accept ,but how we make easier adding functions: that part I don't understand well.
@natillestar
@natillestar 2 ай бұрын
I'm no expert on this topic, but from my understanding there should only be the one member function in each class (type) that accepts any visitor. The visitor knows how to do some operation on a specific set of classes (types). Separating the class (type) from the operation means that if we want to add a new operation to some subset of types, we get to decide which ones we can operate on from the perspective of the operation instead of the perspective of the class (type). With his shapes example, the base is "Shape", and when you start adding operations to Shape, the dependencies are now connected to all Shapes, which may be undesirable. Perhaps you could do multiple inheritance and make the various derived shapes "drawable", "serializable", etc., but this is a different take. Visitor moves the ability to operate on a Shape to outside the Shapes themselves, taking a Shape and knowing how to operate on it to accomplish the operation.
@StevenMartinGuitar
@StevenMartinGuitar Жыл бұрын
I'm hoping that the issue is actually resolved in this talk, but at 11:30ish the issue of having to touch the base class to add more operations... visitor (as far as i know) has the same limitation
@bigbitesaint
@bigbitesaint Жыл бұрын
kzbin.info/www/bejne/p5-ZgKSbm9p7Zpo Link to the type erasure talk
@cesarxxp
@cesarxxp 5 ай бұрын
This is more or leas how Rust works ny default.. Draw would be a trait in Rust
@ABaumstumpf
@ABaumstumpf Жыл бұрын
So with the visitor - something changes aaaand now what? How to make sure that all new shapes implement all the needed functions? You also limit your self and the compiler to the public interfaces. More complexity will tend to reduce performance of the visitor pattern - at least we have seen that several time sin our codebase and while the local code is easier to read understanding what is happening exactly became harder. But in general I am trying to push the code in that direction cause the computations them self are several orders of magnitude faster than other parts of the system and it would help with getting new guys to understand the system.
@onebronx
@onebronx Жыл бұрын
> How to make sure that all new shapes implement all the needed functions? You get a compiler error if an operation you declared as a "must have" is not yet implemented. The problem is not in implementing new operations (you'll need to do this anyway), the problem is how to do this non-intrusively, i.e. without diving into the guts of the existing library, but extending it outside, like with plugins. > You also limit your self and the compiler to the public interfaces. This is a price of extensibility. Also, if your class' private members should be used in operations involving external dependencies, like painting using multiple representations, serializing using multiple encoding, etc, then probably your class breaks SRP, and it is time to make it leaner, may be even reducing to a simple value type with a minimum of behavior.
@ckjdinnj
@ckjdinnj 7 ай бұрын
For me I don’t really see a benefit. This seems like the kind of thing you end up implementing to duct tape a solution together for a codebase that has lived for way too long and or grown too big.
@00jknight
@00jknight 4 ай бұрын
We need a new word! Let's call it 'auto procedural programming'.
@treyquattro
@treyquattro Жыл бұрын
our processors don't support our software well: that's the implicit issue. The OO solution _should_ be the best solution, but it doesn't scale well with our hardware architecture model, even if much work has gone into trying to keep cache lines filled and branches correctly predicted. It seems that as software engineers we have to do significant work to try and maintain processor efficiency as high as possible, and programmers outside of the C++ community are likely to think less about this stuff, if at all. How many programmers even know what's going on inside the processor these days?
@NXTangl
@NXTangl Жыл бұрын
I'm not sure the virtual call case can be handled well by hardware, short of some kind of (likely very brittle) "heads-up" opcode in order to prefetch and pre-pipeline into a call. My intuition is further emphasized by the fact that the Mill guys aren't even trying to optimize dynamic dispatch, despite the whole architecture centering on being able to execute ordinary code as if it were an inner loop.
@RobBCactive
@RobBCactive 6 ай бұрын
Unfortunately DRAM is slow but it can be amortized by reading chunks of data in cache lines, that makes parallel arrays of data pre-fetchable while prettily organised extensible code with abstract types using indirection is slower.
@rationalcoder
@rationalcoder Жыл бұрын
Gotta love when people go the long way around and end up with the obvious tagged union approach that we've had since forever. If you're thinking about Object-Oriented Programming and patterns and what's theoretically going to be a good design, you're doing it wrong. You should be thinking about more fundamental ideas like performance, decoupling, systematization, minimalism, etc., and always in the context of solving a concrete problem. The code will tell you what needs to happen to it over time if you listen.
@zxuiji
@zxuiji Жыл бұрын
21:38, you don't need them, you need a dynamic static array, at the start before you ever use the class you register the classes in use along with their callbacks, you then can have the global visit() etc functions use take registered IDs to identify where in the array to select the actual function from, you destroy the array only at the exit of the program. Still, looking at what you've shown so far it seems the c++ community is taking the long route to learning C is better for control, despite it lack of the awkward semantics you lot introduce to your extension of the language it ends up being both easier to understand and easier to adapt, I can only sit amused by how long you're taking to re-learn what programmers in the early days learnt without fuss. Even I who was just a teenager when I first dabbled in programming realised quickly that C gave me everything I wanted after I learned how inflexible object oriented programming and a lack of types was via javascript
@dkosmari
@dkosmari Жыл бұрын
Talk about completely missing the point, like the typical C programmer stuck in the 70s. In the real world, you need to maintain the code, that was brought up repeatedly in the talk. Once you closed down the types and operations, of course you can make a super optimized version with no types at all, not even functions. By the way, did you know C copied some of the C++ "extensions"? How do you sleep at night, knowing C was "tainted?"
@AlFredo-sx2yy
@AlFredo-sx2yy 10 ай бұрын
this pattern is a total and complete antipattern.
@hampus23
@hampus23 9 ай бұрын
no
@roganjosh6220
@roganjosh6220 6 ай бұрын
Definitely. Ugly, boilerplate-ridden, and a minefield for common OOP-reference pitfalls. Worth using only with a massive amount of understanding and articulation
@treyquattro
@treyquattro Жыл бұрын
good, thought-provoking talk from Klaus Iglberger as always. But is the CppCon idea to dribble out sessions until CppCon 23 rolls around? I guess the amount of material is testament to C++ and CppCon's popularity!
std::variant
17:51
CopperSpice
Рет қаралды 8 М.
Design Patterns: Examples in C++ - Chris Ryan - ACCU 2023
1:39:33
ACCU Conference
Рет қаралды 6 М.
The World's Fastest Cleaners
00:35
MrBeast
Рет қаралды 135 МЛН
НЕОБЫЧНЫЙ ЛЕДЕНЕЦ
00:49
Sveta Sollar
Рет қаралды 7 МЛН
Не пей газировку у мамы в машине
00:28
Даша Боровик
Рет қаралды 6 МЛН
Understanding The Visitor Design Pattern
32:08
Ryan Schachte
Рет қаралды 56 М.
Let's get comfortable with SFINAE (C++)
35:55
platis.solutions
Рет қаралды 2,7 М.
Back to Basics: Exceptions - Klaus Iglberger - CppCon 2020
1:01:45
-memory-safe C++ - Jim Radigan - CppCon 2022
1:05:45
CppCon
Рет қаралды 21 М.
Я Создал Новый Айфон!
0:59
FLV
Рет қаралды 3,1 МЛН
Я Создал Новый Айфон!
0:59
FLV
Рет қаралды 3,1 МЛН
M4 iPad Pro Impressions: Well This is Awkward
12:51
Marques Brownlee
Рет қаралды 6 МЛН
Apple ХОЧЕТ, чтобы iPhone ЛОМАЛИСЬ чаще?
0:47
ÉЖИ АКСЁНОВ
Рет қаралды 1,3 МЛН
APPLE УБИЛА ЕГО - iMac 27 5K
19:34
ЗЕ МАККЕРС
Рет қаралды 92 М.