5 kyu

Readable Specification Pattern

Description
Loading description...
Fundamentals
Object-oriented Programming
Design Patterns
View
AllIssues3Questions1SuggestionsShow Resolved
  • Please sign in or sign up to leave a comment.
  • MrCookies78 Avatar

    Overriding init and new doesn't work. So, I'm supose to magically infer how the function 'get_sample_classes' works?

    • Boniaszewski Avatar

      I have the same problem... this task seems to me unclear because nothing works. I completed the easier one and I though this is in the same manner but it is senseless to guess what to do

  • Boniaszewski Avatar

    I don't get it at all. I defined __ and __ and __ or __ methods in Specification class and in test cases I keep getting the following error: TypeError: unsupported operand type(s) for &: 'type' and 'type'. I though that Water and Hot classes inherit from Specification class... Any hint?

  • Expurple Avatar

    Great challenge ✌️

    For people having trouble with it, I've created an easier version that requires less guessing and hacking

  • Awesome A.D. Avatar

    This comment has been hidden.

    • FArekkusu Avatar

      This kata requires you to use a specific language feature - either you know it, and the task is very simple, or you don't know it, and the task is (probably) impossible to solve. I don't know what you have tried already, but at least your current solution is wrong, and without changing the approach you won't achieve anything.

    • natan Avatar

      Doesn't help that some very key information only exists in the "BTW NOTE" as opposed to being part of the actual description of what's to happen.

      I would much rather receive predicates and return values that exhibit the described behaviour, but I guess if one takes away the OOP from an OOP design pattern it's no longer difficult enough that anyone would think it needs a name XD

  • Blind4Basics Avatar
    • FArekkusu Avatar

      Added this for sample tests and removed the related comments. Also removed unneeded stuff from the note in the description.

      Issue marked resolved by FArekkusu 5 years ago
  • Blind4Basics Avatar
    """
    As the implementation of the "Drink" and "Hot" classes would serve as a hint,
    you have to define them yourselves to make the sample tests runnable:
    
    Drink - checks that the "state" field equals "fluid".
    Hot - checks that the "temperature" field equals "hot".
    
    The final tests will be handled for you, though.
    """
    

    wut?? :o => Just put them into the preloaded section, it's made for this kind of stuff ;p
    Without them your sample tests are close to useless!

    (And don't tell me that they are not in the preloaded section because the user could see what's in there, because he can do that anyway with the full test suite. So there is no point to make the sample tests unusable like that)

    Note: your specification (the text above) isn't enough for a user to build something relyable himself. You're forcing him to poke randomly in the dark and to make assumptions. And considering the "weirdness" of your requirement (I'm not arguing, here. Just a fact), there is close to no chances that he implements his "mocks" in a usable way, compared to the full test suite. ;)

    • FArekkusu Avatar

      Just put them into the preloaded section

      And introduce a circular dependency? Not happening.

      he can do that anyway with the full test suite

      I'm not sure how the users can see the classes' definition, but if they manage to get a hint from the error messages or somehow else, I'm fine with that. I've rewritten the message in the sample tests, and provided a template of what Drink and Hot should look like, but I'm not giving away the actual implementation.

      Issue marked resolved by FArekkusu 5 years ago
    • Blind4Basics Avatar

      This comment has been hidden.

  • Blind4Basics Avatar

    This comment has been hidden.

    • FArekkusu Avatar

      by investigating further, you're doing stuff through some other method, with the classes you're defining. That's pretty unusual. That's not specified.

      "Instead, you should implement a much more beautiful specification pattern by getting rid of those annoying class instantiations" - the description says you're not supposed to instantiate anything (it may not be clear that this rule also applies to the imlemented class/metaclass, so I agree that this could be mentioned), so using __init__ is incorrect (point #2). As you can't initialize any Specification, defining __bool__ achieves nothing (point #1). The only way to make Specification(value) behave as a boolean is to make it an actual boolean, and I think there's only 1 way to do so (point #4). I can add a note that calling the specification-class should return a boolean, but I'm not sure whether that will be of much help, and figuring all this stuff out is supposed to be a part of the task (point #3), so providing more details would spoil it.

    • Blind4Basics Avatar

      Mmmmh, I don't see all of that this way.

      "you" could still build all the constraints the way you currently do it and when the call is done with the arguments, you perfectly can build the actual instance, with a __bool__ method that will do the work for the condition. I see what you said about "getting rid of the instanciations", but imo, you took this too far. I mean: This is about OOP patterns, right? Though you have no instances anywhere, currently.
      Moreover, about OOP, what you currently do is an antipattern: using an instanciation syntax, like Drink(stuff) or (... & ...)(stuff), that returns something else than an object actually inheriting from Specification is... an antipattern, as I said (to me, at least).

      Note that with what I suggest, you still actually get rid of all instanciations, except the last one (I mean: on the user side. What's happening under the hood isn't his problem). So that doesn't change the interface, just the way it works. And about OOP pattern, this is imo more consistent because if you get in the end an actual instance, you can add new behaviors on it. Like, add methods __add__ and __radd__ and you could compute the cost of the resulting class at the same time (you sort of mix your approach with a decorator pattern).

      In my mind, if you work with OOP design, you need to end up with actual objects/instances. Am I clear enough?

      EDIT: might be somehting isn't clear enough about the way I see the problem: for now, my approach is to build intermediate classes on the fly. So Hot & Dink is building a HotAndDrink class, that can be instantiated with (Hot & Dink)(stuff). Are we on the same page about that?

    • FArekkusu Avatar

      using an instanciation syntax that returns something else than an object actually inheriting from Specification is... an antipattern

      That's an opinion. It might be a weird choice to do so, but it's a valid and documented language feature, and I don't see anything bad in using it.

      you still actually get rid of all instanciations, except the last one... this is imo more consistent because if you get in the end an actual instance, you can add new behaviors on it

      But I want no instances! :angry: The argument about additional behavior is irrelevant. It doesn't have to be expandable or follow some state-of-the-art software architecture design, because there is no architecture - you're supposed to implement 1 very specific feature with very specific behavior, and nothing more.

      Of course, the current test setup enforces a specific implementation, but that's exactly the point: there's an additional challenge of making Specification a boolean instead of just imitating it, and I won't to keep it this way. If the intent is not clear, as I said, I can add a note about how it should work.

    • Blind4Basics Avatar

      This comment has been hidden.

    • FArekkusu Avatar

      you need to tell at the very least the contract you use for those base classes... did you update the preloaded section with the base classes?

      As I said, figuring out how to solve it is a part of the task. It was never intended for the description to explain the contract or for the sample tests to show any classes inheriting Specification.

      I've added a very clear note about the expected behavior in the description, and a few sample test which explicitly check that the returned value is a boolean.

      Issue marked resolved by FArekkusu 5 years ago
    • Blind4Basics Avatar

      okay, but you need to add that at the end too:

      ...but return True/False itself, just like Drink(drink) and the other base classes extending Specification will do.

      Without that, you're still hiding the "base" of the mechanics

  • siebenschlaefer Avatar

    This comment has been hidden.

    • FArekkusu Avatar

      The problem is that I'm working with the classes directly while you're ignoring this fact and creating instances. The only hint I can give is that the built-in method for creating instances can be used as a predicate.


      Edit:

      To do so you have to create a class Specification which will be inherited by other classes

      Your solution works only as long as you yourself create all the classes for the Specification pattern. Obviously, this won't work when all the setup is performed in the tests.

    • FArekkusu Avatar

      As I said, your approach is wrong. If you still want to try and solve the kata, there're sample tests now which work in the same way as the final tests, and you don't have to define anything yourself to make them runnable.

      Question marked resolved by FArekkusu 5 years ago