Preferences

bedobi
Joined 2,604 karma

  1. Your price could simply be an interface that both Student and Employee implements, and at the call site, you simply call foo.calculatePrice - Student will calculate it one way and Employee another, there is zero need for inheritance, or for the call site to know which object is which of the two types - all it needs to know is it has the calcultePrice interface.

    I also prefer pattern matching over dynamic dispatch. But I maintain that conjuring up attributes out of thin air (which is 100% what you're doing when your function accepts one type, and then inside, conjures up another, that has additional attributes from the input!) is insane. There are so many good reasons not to want to do this I don't even know where to begin. For one, it's a huge footgun for when you add another type that inherits - the compiler will NOT force you to add new branches to cover that case, even though you may want it to. Also, such "reusable" if this then do this else do that methods when allowed to propagate through the stack means every function is no longer a function, it's actually *n functions, so ease of grokking and maintainability goes out the window. It's much better to relegate such ifs to the edges of the system (eg the http resource endpoint layer) and from there call methods that operate on what you want them to operate on, and do not require ifs.

  2. for one, see the reply from the handle cryptonector further up

    > Inheriting from a class creates dispatch problems, and there's instance variables/fields/whatever to deal with. Never mind multiple inheritance, as that gets hairy real fast. With interfaces there is no hierarchy, and all there is is a type and a data, and you either pass them around together, you monomorphize to avoid the need to pass two pointers instead of one, or you have the data point to its type in a generic way. With class hierarchies you have to have operations to cast data up and down the hierarchy, meaning trade one dispatch table for another.

    I agree with all of this. With interfaces, you get all the benefits, but none of the downsides.

  3. this! with interfaces, you get all the benefits and none of the negatives
  4. I agree that there are better ways to model roles and FGA

    the point of the example wasn't to be an idiomatic solution to that problem, but to illustrate the pointlessness of inheritance in general, and User Student Employee was the first thing that came to mind that was more "real" than the usual Animal examples

    in any case, as for only having a User reference, you don't ever have only a User reference - overwhelmingly you would usually load a Student or Employee,

    and each of them would have those attributes on them that characterize each of them respectively (and those attributes would not be shared - if they were, such shared attributes would go on the User object)

    only those functions that truly are operating only on User would you send in each of their User objects

    the problem with what you're advocating is you end up with functions like this

        fun doSomething(user: User) { if (user is Student) { do this } else { do that } }
    
    which is insane
  5. I happily admit it's more than possible to come up with examples that make inheritance shine. After all, that's what the authors of these books and articles do.

    But most of them put the cart before the horse (deliberately design a "problem" that inheritance "solves") and don't seriously evaluate pros and cons or even consider alternatives.

    Even then, some of the examples might be legitimate, and what you're referring to might be a case of one. (though I doubt there's no equally elegant and succinct way to do it without inheritance)

    But none of that changes the fact that inheritance absolutely shouldn't be the default goto solution for modeling any domain it has become (and we are taught to understand it as)

    or that it's exceedingly uncommon to come across situations like yours where you have 500+ shared cases of behavior and you only want to "override" 5

    or that inheritance is overwhelmingly used NOT for such niche edge cases but as a default tool to model even the most trivial relationships, with zero justification or consideration

  6. > The alternative is that you wind up implementing the same 5-10 interfaces repeatedly for every different object you create.

    if both Student and Employee need to implement those interfaces, it's probably User that should have and implement them, not Student and Employee (and if they truly do need to have an implement them, they can simply delegate to their internal User = "no override" or provide a unique implementation = "override") (let alone that unless I'm misremembering in Kotlin interfaces can have default implementations)

  7. I see no need for inheritance there, that can and should be done using interfaces

    eg in the contrived example I gave, any of all three of the User, Student and Employee can implement the interface (and if needed Student could simply delegate to its internal User while Employee could "override" by providing its own, different implementation)

  8. Do yourself a favor and wear yourself off all this SOLID, Uncle Bob, Object Oriented, Clean Code crap.

    Don't ever use inheritance. Instead of things inheriting from other things, flip the relationship and make things HAVE other things. This is called composition and it has all the positives of inheritance but none of the negatives.

    Example: imagine you have a school system where there are student users and there are employee users, and some features like grading that should only be available for employees.

    Instead of making Student and Employee inherit from User, just have a User class/record/object/whatever you want to call it that constitutes the account

        data class User (id: Int, name: String, email: String)
    
    and for those Users who are students, create a Student that points to the user

        data class Student (userId: Id, blabla student specific attributes)
    
    and vice versa for the Employees

        data class Employee (userId: Id, blabla employee specific attributes)
    
    then, your types can simply and strongly prevent Students from being sent into functions that are supposed to operate on Employees etc etc (but for those cases where you really want functions that operate on Users, just send in each of their Users! nothing's preventing you from that flexibility if that's what you want)

    and for those users who really are both (after all, students can graduate and become employees, and employees can enroll to study), THE SAME USER can be BOTH a Student and an Employee! (this is one of the biggest footguns with inheritance: in the inheritance world, a Student can never be an Employee, even though that's just an accident of using inheritance and in the real world there's actually nothing that calls for that kind of artificial, hard segregation)

    Once you see it you can't unsee it. The emperor has no clothes. Type-wise functional programmers have had solutions for all these made up problems for decades. That's why these days even sane Object Oriented language designers like Josh Bloch, Brian Goetz, the Kotlin devs etc are taking their languages in that direction.

  9. This is a solved problem and it's astonishing the world hasn't just adopted the Dutch traffic engineering standards outright. It's FASTER for cars and safer for people.
  10. London Underground destroys all other transit on the planet when it comes to noise, and ironically, it's not even the trains themselves, it's the effing speakers

    MIND THE GAP

    louder than an Iron Maiden concert, it's unbearable and unnecessary, no idea why they don't turn that shit down

  11. Even if the post accurately reflects your lived experience, if it's AI generated, ultimately it is just that, generated by an AI, who is not you. People can smell that from a mile away, and they dislike it. (as they should!)

    Get over your anxiety over your writing and just share your authentic self. How good or bad a writer you are doesn't really matter. (like OK it has to be legible but beyond that no one is expecting perfection)

    It's whether the story you're telling, the experience you're sharing etc is thought provoking that matters.

  12. A lot of Robert C Martins pieces are just variations on his strong belief that ill-defined concepts like "craftsmanship" and "clean code" (which are basically just whatever his opinions are on any given day) is how to reduce defects and increase quality, not built-in safety and better tools, and if you think built-in safety and better tools are desirable, you're not a Real Programmer (tm).

    I'm not the only one who is skeptical of this toxic, holier-than-thou and dangerous attitude.

    Removing braces from if statements is a great example of another dangerous thing he advocates for no justifiable reason

    https://softwareengineering.stackexchange.com/questions/3202...

    Which caused the big OSX/iOS SSL bug in 2014, see https://www.imperialviolet.org/2014/02/22/applebug.html

    This link and thread on hackernews is good too

    https://www.hackerneue.com/item?id=15440848

        The current state of software safety discussion resembles the state of medical safety discussion 2, 3 decades ago (yeah, software is really really behind time).
    
        Back then, too, the thoughts on medical safety also were divided into 2 schools: the professionalism and the process oriented. The former school argues more or less what Uncle Bob argues: blame the damned and * who made the mistakes; be more careful, damn it.
    
        But of course, that stupidity fell out of favor. After all, when mistakes kill, people are serious about it. After a while, serious people realize that blaming and clamoring for care backfires big time. That's when they applied, you know, science and statistic to safety.
    
        So, tools are upgraded: better color coded medicine boxes, for example, or checklists in surgery. But it's more. They figured out what trainings and processes provide high impacts and do them rigorously. Nurses are taught (I am not kidding you) how to question doctors when weird things happen; identity verification (ever notice why nurses ask your birthday like a thousand times a day?) got extremely serious; etc.
    
        My take: give it a few more years, and software, too, probably will follow the same path. We needs more data, though.
  13. The sane thing to do is to let lower layer functions return

        Either<Error, Foo>
    
    then, in the HTTP layer, your endpoint code just looks like

        return fooService
                    .getFoo(
                        fooId
                    ) //Either<Error, Foo>
                    .fold({ //left (error) case
                        when (it) {
                            is GetFooErrors.NotAuthenticated -> { Response.status(401).build() }
                            is GetFooErrors.InalidFooId -> { Response.status(400).build() }
                            is GetFooErrors.Other -> { Response.status(500).build() }
                        }
                    }, { //right case
                       Response.ok(it)
                    })
    
    the benefits of this are hard to overstate.

    * Errors are clearly enumerated in a single place. * Errors are clearly separated from but connected to HTTP, in the appropriate layer. (=the HTTP layer) Developers can tell from a glance at the resource method what the endpoint will return for each outcome, in context. * Errors are guaranteed to be exhaustively mapped because Kotlin enforces that sealed classes are exhaustively mapped at compile time. So a 500 resulting from forgetting to catch a ReusedPasswordException is impossible, and if new errors are added without being mapped to HTTP responses, the compiler will let us know.

    It beats exceptions, it beats Go's shitty error handling.

  14. that's easy to fix, just make the light brighter
  15. > everyone there is contributing to the energy by actually having a good time, instead of being preoccupied with showing people who are not with them that they are having a good time

    this screams "economists, behavioral economists, game theorists, sociologists and anthropologists" would love to study this"

    people from all the above disciplines, where are you? this is your phd thesis

  16. the disconnect here is you have a status quo biased thinking

    the current state of things is, roads get all the money and transit and bike infra get scraps and are poorly run (so are FDOT road projects too btw)

    no one disputes that?

    what is being advocated is increasing trirail frequency, implementing an actual network of segregated greenways and expanding metrorail

    you're saying "oh we can't do that"

    but like, yes, we can? I promise you, if you send out construction crews to apply green paint and put down curbs for greenways, there's no natural law of the universe that would make the paint not come out

    and once it's in place, there's nothing preventing millions of Miami residents from using them the same way they're being used in NYC, Montreal, Barcelona etc etc instead of having to get in the car for literally every single trip and errand

    likewise if you procure trains there's no magic wall that prevents them from crossing into the state of Florida etc etc

    these things are trivially achievable, but misinformed policymakers and voters alike think adding more roads is somehow not costing any money (it costs way more) and will fix traffic (it won't)

  17. you're just being obtuse

    in the realm of infrastructure investment, all of that is overnight

    vs eg the yet another additional bridge to nowhere they're currently building that is taking decades and costing billions

    but tell you and every other frothing at the mouth motorist what, enjoy sitting in traffic

  18. > So are public transit riders. And to a worse degree. What's your point?

    that this is wildly incorrect. roads cost more than transit. a lot more. and road users are wildly more subsidized than transit users.

    > We should magically spawn mass transit systems overnight

    yes

    > and force everyone to ride them?

    you won't have to when the choice is between sitting hours in traffic vs a fraction of the time on efficient transit and greenways. people are not stupid.

    > It just isn't a viable option in ~80% of the US

    this is Miami, not middle of nowhere Iowa

    > Rome wasn't built in a day

    so it's correct of Miami to continue to "invest" in even more roads to nowhere, like yet another new highway bridge across the bay? that will take decades to complete and cost billions, and cause MORE traffic?

    like no lol just build the effing transit and greenways and traffic will go down and the government and people alike will save billions instead (and their time, and lives)

  19. they can, they just malinvest in roads that only increase traffic and make things worse and cost even more

    instead of transit which saves money

  20. lol the idea isn't to make money off transit, it's to save money on roads

    roads cost more than transit - a LOT more, and motorists aren't paying anywhere near the cost of road construction and maintenance, they're (quite literally) free-riding subsidized trips on the taxpayer

    traffic also destroys productivity, public health, life expectancy etc etc so costs money in many more ways than motorists not paying for them

  21. yeah, all of which can be done overnight
  22. no it would save miami and the state and the federal government billions

    trirail frequency increases can be done overnight

    a greenway network can also be built quickly and cheaply

    metrorail extension would cost more but still less than it costs to build and maintain roads

    but they are too busy spending billions building even more car infra which will only make traffic and congestion even worse

  23. Imagine if instead Miami built MetroRail extensions to the beach and everywhere else it should go, increased TriRail frequency and express services, built a real network of fully segregated greenways etc etc. It would turn transport nightmare into transport heaven. We don't need more cars on the streets of Miami or the I95...
  24. this argument against common sense bike infrastructure is one of the most common, most wrong, and most dumb

    bicyclists, pedestrians and transit users in fact subsidize motorists, in all countries, everywhere. this isn't up for debate. so under your own logic, motorists should have no right to the roads, because they're "freeloading" and "not paying their fair share". sigh.

    ironically, even the most ardent bike infra advocates don't actually think that. they just think the money they're paying shouldn't be expropriated exclusively for motorists, while they themselves get close to nothing, especially when bika infra is so comparatively cheap and efficient (it actually SAVES the government and the public money)

    the benefits of bike infra are obvious and self evident. less pollution, less noise, more mobility for children and the disabled. it benefits motorists too, because it takes traffic off the roads, and saves parents time and money having to ferry their kids around all the time etc etc.

    tbh people like you seem just like hateful selfish misanthropes.

  25. i agree with your sentiment, but it bears pointing out that no one brandishes their underwear in people's faces screaming that they must wear the same ones, or use the political system to privilege people of the same underwear and punish others etc etc

    fwiw me personally i'm all in on uniqlo airism, there is no better underwear and if i could force everyone to wear them i would (for their own good, of course)

  26. Took me three times to parse what you wrote, I thought you were saying Not strength training improves mental clarity and sleep lol
  27. not a fan of the JS or its community either, but there you have objectively better languages and communities like TypeScript

    likewise for embedded and backend Rust and Kotlin are objectively better languages and communities than Go

  28. In Golang, you have to learn to be dumb, because that's explicitly and deliberately what the designer said about the intended users of the language and how it's designed.
  29. Partial instantiation is cool and all, but tbh I prefer just capturing the initial incomplete attributes in one complete record, pass that around, and then instantiate the real thing when you have all attributes

        data class IncompletePerson(val name: String)
    
        data class Person(
          val name: String, 
          val email: String
        )
    
    or

        data class Person(
          val initialAttributes: IncompletePerson, 
          val email: String
        )
    
    if you want to nest it.

    if you're the type to instead do this

        data class Person(
          val name: String, 
          val email: String?
        )
    
    I never want to work with your code. Now, there's no disambiguation between the complete object and the incomplete one, I always have to check before doing anything with it, and people will inevitably try send an incomplete object someplace that can't handle it and generate bugs.

This user hasn’t submitted anything.

Keyboard Shortcuts

Story Lists

j
Next story
k
Previous story
Shift+j
Last story
Shift+k
First story
o Enter
Go to story URL
c
Go to comments
u
Go to author

Navigation

Shift+t
Go to top stories
Shift+n
Go to new stories
Shift+b
Go to best stories
Shift+a
Go to Ask HN
Shift+s
Go to Show HN

Miscellaneous

?
Show this modal