Keynote: SOLID, Revisited - Tony Van Eerd - [CppNow 2021]

Поділитися
Вставка
  • Опубліковано 28 сер 2024

КОМЕНТАРІ • 31

  • @mrguybrush1655
    @mrguybrush1655 3 роки тому +9

    Very informative talk, thank you! I love the historical context, and the visualizations. Really well done!

    • @BoostCon
      @BoostCon  3 роки тому +3

      Much appreciated!

  • @CHR73TANGO
    @CHR73TANGO 3 роки тому +6

    I also think it was a very good talk, so what MrGuyBrush said! :-)
    It was really good with the concrete examples from your projects/product and I think it made for much more realistic examples.

  • @JohnDlugosz
    @JohnDlugosz 3 роки тому +3

    1:08:30 The original C++0x Concepts were even more _like_ contracts. This is one of the things that was removed to give the "Concepts Lite" in C++20.
    That is, by implementing the body of the template in terms of the Concept, using Concept Maps to get to the actual functions, it checks at compile time that the supplied class really does meet the requirements.

  • @kibork1
    @kibork1 3 роки тому +5

    First 13 minutes are just “joking around”, skip if you’re here for the content

  • @nandanvasudevan
    @nandanvasudevan 3 роки тому +2

    This is really GOOD!

  • @thelatestartosrs
    @thelatestartosrs 8 місяців тому +1

    4:36 "if you're only gonna read 1 paper read these 2"

  • @szaszm_
    @szaszm_ 11 місяців тому +1

    22:52 Other languages help with "don't have a bunch of arrows in a line": most of them tend to use a dot instead of an arrow. 😅

  • @xmoex6393
    @xmoex6393 2 роки тому

    I just Tony van Eerd!

  • @tardtron2k
    @tardtron2k 3 роки тому +1

    Ray classes should be made of an origin point, and a vector for direction, not two points. You can derive the direction from the two points, but why? You changed my mind about Circle, thank you. Also, another talk worth watching, thank you.

    • @tvaneerd
      @tvaneerd 3 роки тому

      why? Two reasons:
      1. I have two points. To turn it into a point and a vector would take work (subtract the points, maybe a divide to make it unit length???)
      2. It wouldn't make as good of an example :-)

  • @Dth091
    @Dth091 3 роки тому +3

    Classes are velcro. The fuzzier something is, the more likely it is to get stuck.

    • @Dth091
      @Dth091 3 роки тому

      Just got to the end and seen the "FLUFFY" backronym. Fluffy things also stick to velcro, but the best thing about velcro is it's not a permanent attachment, and they only stick together at the surface. ;)

    • @VioletGiraffe
      @VioletGiraffe 3 роки тому

      I get your point, but that's not a consequence of using classes, only a consequence of designing them poorly. Classes are still much better in many ways than the alternatives.

  • @philbax
    @philbax 3 роки тому +1

    I'm presuming in moving member functions to free functions, those free functions should probably be wrapped in a namespace, yes?

    • @tvaneerd
      @tvaneerd 3 роки тому +1

      Ironically (or was it on purpose!) I refer to Titus by his somewhat unique first name, but Sean by his full name. That's the namespacing talk right there.

    • @tvaneerd
      @tvaneerd 3 роки тому +1

      **Don't over-namespace.** I've got code with 3 or 4 levels of namespacing and it is annoying. `Foo::Bar::Thing::Here::It::Is`... (Particularly because we don't use `using namespace...` and I think it is important to keep it that way.)
      Titus (Titus Winters, watch his talks) is pretty strong that there should only be one level on namespacing.
      Sean Parent (watch all his talks, twice) points out that if you have a name collision
      there is a good chance you actually have some similarity and possibly a concept
      or generic algorithm - `Foo::sort()` and `Bar::sort()` probably both actually sort, maybe there is something worth investigating.
      (Although English is notorious for homonyms, so collisions don't always mean similarity.)
      C++'s ADL (Argument Dependent Lookup, ie overload resolution) is a blessing and a curse.
      If your function is well named and you are using strong types, it is probably uniquely identifiable by name + param types and doesn't need namespacing.
      `draw(Surface, Circle)` is as unique as `Circle::draw(Surface)`.
      `draw(Surface, Circle)` will not be confused with `draw(Cowboy, Gun)`. At least not by the compiler, and probably not by the developer either, in context of other code.
      "When to Namespace" should probably be a whole talk. I'd do that talk if I had a better answer than "I know it when I see it".

  • @toddzankich9200
    @toddzankich9200 3 роки тому

    Is tidy_ptr nullable, like unique_ptr? If so, the image is not a value type, but an *optional* value type, essentially. Besides, not knowing a size (or format), wouldn't `Image()` have to construct a valueless object?
    If so, every function that accepts an image reference, even the get/set-pixel member functions, would have to perform an extra precondition check for valuelessness, and require an alternate route for failure. I think that violates SRP, since every function has extra work/complexity. In a way, it also violates open/closed, because if one were to remove the valueless option, every image-aware function would have to be modified.
    If the default constructor is deleted, and tidy_ptr is nullable, then tidy_ptr would still constitute an interface segregation violation. That's because functions like swapping, releasing, and reassigning pointers would exist when they're never needed.

    • @toddzankich9200
      @toddzankich9200 3 роки тому

      Eventually, getPixel and setPixel disappear, and begin/end appear... instead? Even so, iterating a null image would not make sense, and probably should throw or fail somehow.

    • @tvaneerd
      @tvaneerd 3 роки тому +1

      Image needs a moved-from state anyhow, so empty is mostly unavoidable. And the optional nature can be useful, in the same situations as std::optional. Yeah, that means sometimes checking, but it is caught by begin/end.
      I don't think I understand what you are saying about swapping/releasing/reassigning - those are not exposed in the Image interface.

    • @toddzankich9200
      @toddzankich9200 3 роки тому

      @@tvaneerd An optional aspect is different from a moved-from state. An optional aspect (if present) must be considered for all normal use cases, whereas the moved-from state is "valid but unspecified." The destructor must succeed whenever it's applied eventually, but the object is no longer meaningful in any other sense.
      SOLID principles don't cease to apply within private implementations of classes and/or modules. The fact that you're using (and we all have to use) standard C++ classes with extra, unused features violates the interface segregation principle. C++ (and C, and even Rust) standard libraries are generally unaware of SOLID, if not unintentionally hostile to it! If we were to prune features of even the most fundamental standard classes such as containers and smart pointers, either through protected inheritance, or "using" a public feature of a base class in a "private" section of a derived class, then we'd be violating Liskov's substitution principle. We would not be exposing those violations to our users, but we and our module's future maintainers would still suffer.

  • @bocckoka
    @bocckoka 11 місяців тому +1

    Delegate, delegate, until your responsibility is to call a single CPU instuction. Then watch as new hires flee, horrified by your shit.

  • @williamchamberlain2263
    @williamchamberlain2263 10 місяців тому +1

    Starts at 13:30

  • @David-ws3rw
    @David-ws3rw 3 роки тому

    I would have made Format a template parameter of Image.

    • @tvaneerd
      @tvaneerd 3 роки тому +5

      Yeah, considered that. But then a whole bunch of code (whole app, basically) needs to become a template. Most code wants to pass around a type-erased Image, and doesn't care about the pixel type - only specific image processing code needs to touch pixels. It needs a hybrid. It deserves its own talk...

  • @AdamByrd89
    @AdamByrd89 Рік тому +1

    Feel free to skip the first 12.5 minutes of fluff.

  • @JohnDlugosz
    @JohnDlugosz 3 роки тому

    1:14:00 you need a template conversion operator that takes anything that is represented by two points, rather than listing them all and having identical code in each.
    But really, a line is the same line no matter which two (distinct) points you use; rays have one point and a direction, and holding a second point is just one way of doing that, and it is not a unique value. Perhaps your Ray and Line classes were normalized, and did not necessarily store the same two points that you used to construct them.
    Your ease of conversion is more of an implementation accident than a proper conceptual operation. You CANNOT convert a Line to a LineSegment, as a Line does not pick up any specific segment.

    • @tvaneerd
      @tvaneerd 3 роки тому

      All true. (You can convert in one direction though: segment -> ray (2 choices of which ray - which endpoint) -> line).
      Mostly the point is in the example, not the details. It is an example of something that "looks" the same or related. Maybe I did too much hand-waving in an attempt to convince people that they seem the same.

    • @pmcgee003
      @pmcgee003 2 роки тому

      @@tvaneerd algebraically, it might seem nice to consider a ray as fundamental, a line as a union of rays, and a segment as an intersection ... but I dunno about that helping you do fast engineering calcs ...