1. 36
  1.  

  2. 8

    I’m not sure I understand forcing things into classes when literally all the methods are staticmethod. If the point is purity and always passing in all needed input data without needing to carry internal state (and the classes have no members aside from their methods anyway), why not just replace the class with a set of functions in a module?

    1. 9

      It’s a readability thing:

      Please note that examples will use the classes+static method form in order to make this article readable. In a production code, the modules+functions form is the way to go.

      1. 4

        I was thinking the same thing. It’s probably just for pseudo namespacing within a single file instead of 3 separate modules. Total guess though.

        Edit: Also hey @ubernostrum! I’ve followed your for years via Django (maybe since 0.96 days), but hadn’t seen you in a few years. Just noticed that was you. Thanks for all your work.

        1. 4

          Indeed, in Python, having a module with a set of functions would be more appropriate.

          I guess that the reason the author of the article used Python classes is related to the fact that in the book, I have illustrated the separation between code and data using JavaScript classes instead of JavaScript modules.

          My idea was to illustrate how separation between code and data could be applied even in languages where everything has to be a class (e.g. Java). But in languages that support module (or namespace) like Python, JavaScript and Clojure, I think it’s better to avoid classes for aggregating functions.

          1. 2

            Besides readability (classes can act as a namespacing construct within a module), you can use classes to define environmental data (ie. secrets, urls, host/ports, etc), in a pattern like so:

            class MyAPI:
               def __init__(self, environment):
                  self.environment = environment
            
               def perform_action( self, arg ):
                  ....      
            

            and then

            api = MyAPI(...)
            api.perform_action(...)
            

            The key problem with DOP is that if you’re doing concurrent state updates, you end up with two distinct state branches that need to be merged. This is a slow operation unless the transforms are incremental (consume the previous state, a data atom, and produce a delta on the previous state). If Python gets immutable data structures and differential dataflow primivitives, then this will be much easier and performant!

            1. 2

              Indeed managing concurrent mutations with mutable data structures is not efficient. In the book, I am devoting Chapters 4 and 5 to illustrate how immutability make it more efficient using Lodash FP.

              I would love to see a similar implementation in Python. Maybe pyrsistent can help?

              1. 1

                What do you mean by efficient? I suspect that the kernel and the JVM runtime would be massively slower if they couldn’t use atomics and compare-and-exchange primitives.

                1. 1

                  Could you elaborate a bit?

            2. 1

              it tends to get a lot of pushback, but i personally like the use of classes as namespaces for a bunch of related functions.

              1. 2

                I agree. It can be nice if you want to write something in a single file and still have some namespacing.

            3. 3

              Sounds like an interesting book. Would love to hear from others what their experiences with this are.

              1. 2

                The original ‘Data Oriented Design’ book was a good read. I wonder if this might be a more approachable introduction? The techniques are great, but that’s not a surprise: it’s relational design.

                1. 3

                  Author of the book here: The book is about “Data-Oriented Programming” not about “Data-Oriented Design”.

                  1. 4

                    Ah, I hadn’t read closely enough. The naming is deceiving. How is this different from functional programming, or maybe just “program like you’re writing Standard ML”?

                    1. 1

                      DOP embraces generic data structures like string maps to model domain data. DOP separates between data representation and data validation.

                      1. 1

                        Okay. I can see how that comes out of the Clojure community. More like how you do FP in Erlang than ML.

                        1. 1

                          Exactly!

                          In the book, the character that unveils the secrets of DOP presents himself as a Clojure developer.