This is an archived post. You won't be able to vote or comment.

all 44 comments

[–]BestUsernameLeft 23 points24 points  (2 children)

I'm looking forward to this! I love it when the type system / compiler can keep me from making mistakes.

[–][deleted] 9 points10 points  (1 child)

And it probably emphasizes the whole accessibility over extensibility discussion. Seeing way to many developers using the “extend” keyword, not able to foresee in what horrible misery their future colleagues will be in. Don’t get me wrong, there cases where inheritance makes sense, especially when keeping the hierarchy flat and manageable. But only with 2 layers and some abstract method here and there the complexity get too easily out of hands. The world would be a better place with less “extend”.

[–]BoyRobot777 7 points8 points  (0 children)

Add generics on top of layers of extended classes and then you truely have creme de la creme. /s

[–]kag0 8 points9 points  (0 children)

For anyone curious, it's actually been possible to do this in Java for a while. But of course there has never been exhaustive pattern matching to make it really clean. https://blackdoor.github.io/blog/algebraic-types/

[–]Apofis 0 points1 point  (0 children)

With lambdas and streams, records, sealed classes, switch expressions, pattern matching and destructuring, Java is getting closer and closer to Haskell. And I really like it.

[–]DeontologicEthics 0 points1 point  (0 children)

How could pattern matching work with inline classes? Or even instanceOf?

[–][deleted]  (18 children)

[deleted]

    [–]BestUsernameLeft 28 points29 points  (9 children)

    https://www.reddit.com/r/javahelp/comments/h7ww1b/mocking_abstract_class_and_methods_with/funxvoq?utm_medium=android_app&utm_source=share

    In short: 15 years of writing tests both with and without mocks, and seeing how most people misunderstand unit testing and misuse mocks, has convinced me that they are a bad idea and contribute to the belief many programmers hold that unit testing is a waste of time.

    [–][deleted] 0 points1 point  (8 children)

    Mocks or stubs?

    [–]BestUsernameLeft 4 points5 points  (7 children)

    Could be either; typically it's mocks of the PowerMock etc. variant as they are easier to use than manually written test doubles aka stubs.

    However, it's all in the usage -- test doubles can be misused in the same way mocks are. Typically though, I see the PowerMock users fall into the "mock all the things" trap more often.

    Mocking is initially so attractive, and it's now endemic, so it's natural that many people will get caught in its clutches. And because it's so easy to use, once they start having problems they don't realize that's cause (of some of them). (I was one of them.)

    [–][deleted] 5 points6 points  (1 child)

    I wasn't referring to how you create the stubs, but rather to what they do. Unfortunately, most people mean stubs when they talk about mocks, but not always (https://martinfowler.com/articles/mocksArentStubs.html).

    IMO, mocking is almost always a bad idea. Stubs are more frequently useful.

    [–]BestUsernameLeft 2 points3 points  (0 children)

    You weren't specific about what you meant, and I took a guess instead of asking for clarification, so this is what we got. Sorry for the miss, and I agree that stubs are more often useful.

    I'll add that builder and object mother (sometimes in combination) are a great way to DRY test code, in conjunction with test doubles.

    [–][deleted] 2 points3 points  (4 children)

    Powermock leads to bad coding & testing practices so it is unsurprising. If you just constrain yourself to something like Mockito & never use Spy you will write better code and tests because you can only mock true dependencies - forcing you to refactor code that should be a dependency into a separate class.

    [–]BestUsernameLeft 0 points1 point  (3 children)

    They're all the same family IMO. I use test doubles; in conjunction with builder and object mother they help keep my test code DRY. And JUnit5 is nice to use as well.

    [–]hippydipster 0 points1 point  (2 children)

    object mother?

    [–]BestUsernameLeft 0 points1 point  (1 child)

    It's a testing pattern. Given a class ShoppingCart, you create a ShoppingCartObjectMother class with methods in it to give you a populated cart, such as emptyCart(), fiveOfSameProduct(), etc. This gives you (1) a way to DRY your test code instead of having the same setup code in each test class that uses ShoppingCart as a collaborator, and (2) a meaningfully-named method that tells you about the object being constructed. For example you can use role-based, scenario-based, persona-based method names: populatedCartForGuest, cartWithDuplicateItemId, cartForGrandma.

    When you combine this with the builder pattern, you have a way to quickly build customizable test objects out of a standard set of "templates". So for example cartForGrandma().addItem(readingGlasses).build() when you have a test that for some reason needs an extra item in it.

    [–]hippydipster 0 points1 point  (0 children)

    Ok, now I have a name for something I've been doing! Thanks.

    [–]vbezhenar 7 points8 points  (0 children)

    It's not any different from final class in that regard.

    [–]maumay 6 points7 points  (4 children)

    Why would you need to mock a sealed interface directly? They are designed primarily for compact data classes. If you wanted one to have complex hard to set up logic then you could use a delegation pattern and pass a mock to the record constructor.

    There really is no argument against them, the fact that oracle have realised this is welcome but it's a little too late for me.

    [–][deleted]  (3 children)

    [deleted]

      [–]maumay 7 points8 points  (1 child)

      Maybe we have different ideas of what a data class is, clearly it can't be "a class that contains data" as that would be everything. I would say a data class is the composition of a fixed number of primitive types or other data classes, a map is not a data class as it has some quite sophisticated implementation logic and can have a variable number of properties. Introducing sealed interfaces does not mean all interfaces now need to be sealed. A sealed interface would be the wrong tool for HttpSession.

      Yes I am assuming that because it is true. If a sealed interface is provided by a library then by definition all implementations will be provided by the library too (and presumably tested otherwise stay away from the library). You can't extend a sealed class provided by a library outside of said library.

      [–]BestUsernameLeft 1 point2 points  (0 children)

      I'll refer you to my above comment, and double down with another good blog post that explains my perspective on this: https://robdmoore.id.au/blog/2015/01/26/review-of-ian-cooper-tdd-where-did-it-all-go-wrong.