Classes vs. Data Structures - <AUTHOR> http://blog.cleancoder.com/uncle-bob/2019/06/16/ObjectsAndDataStructures.html <comment><USER2> People are starting to use data oriented design instead of OOP. Data oriented design doesn't hide state, is generally faster and easier to comprehend as it doesn't abstract too much.

[https://www.youtube.com/watch?v=QM1iUe6IofM](https://www.youtube.com/watch?v=QM1iUe6IofM) [https://www.youtube.com/watch?v=yy8jQgmhbAU](https://www.youtube.com/watch?v=yy8jQgmhbAU) [https://www.youtube.com/watch?v=rX0ItVEVjHc](https://www.youtube.com/watch?v=rX0ItVEVjHc)

<comment><USER3> Data oriented design makes sense in video games where perfomance Is very important, but in most business applications having good abstractions which are flexible and easily maintainable is much more important than optimising for cache usage.

<comment><USER4> I keep hearing this from OOP proponents, but I just don't find it to be true in my experience. Programs written with DOD in mind have very clear data flow and only pass on and use data that is relevant. Programs written with OOP in mind primarily care about some notion of beautiful code and abstractions, which I find to be highly subjective. As a result they generally have very muddy data flow where e.g. unrelated data is passed around that isn't even required to implement a feature. This creates all kinds of poor modularization, dependency hell, huge monoliths, difficult testing (mocking, fakes, etc...), among many other problems. Whenever I have had to rewrite large parts of a program, I have always found it to be easier to do this in a DOD program rather than an OOP program. The _biggest_ reason why DOD is used in video game programming to begin with is flexibility in mixing and matching functionality of game objects (entity-component-systems etc).

</comment></comment></comment><comment><USER5> I guess this applies for Java and C++ style "classes". This does not precisely apply to the first ANSI-standardized OOP system, Common Lisp's. Standard classes do not own methods, instead methods are specializations of a generic function that stands alone and dispatches on the class types (or EQL values) of all its arguments.

I'd really like it if Uncle Bob eventually has his fill of Clojure and moves on to explore what Common Lisp built decades earlier, then blogs about that too.

<comment><USER6> Came here to say exactly this and you already did, so thanks. It's amazingly liberating to use a language where generic functions are first-class, and classes don't own any methods. Once you've written code this way, the other way seems backward and restrictive.

<comment><USER7> Spot on. Multiple dispatch avoids the whole issue because methods are external and don't live inside of classes. Lisps, of course support multimethods, which is great. There are some down sides, though. They are opt-in (defmethod) and tend to have a significant performance hit associated with them. Someone needs to anticipate your need to add types and/or functions _and_ think it's worse sacrificing performance for that ability.

Julia, builds on this tradition but allows you to have your cake and eat it too. It has multimethods/generic functions _and_ they are the only option—all user defined functions are multimethods. They also have excellent performance (they're used for everything, they have to).

Of course, there's no free lunch and you do give up traditional separate compilation, but the degree composability it gives to the ecosystem is hard to comprehend without experiencing it. Simple, reusable data types are shared across the ecosystem with anyone adding whatever (external) methods they want. Generic code that handles a literally exponential explosion of argument types "just work"—and the compiler generates fast code. All without doing anything special, since multiple dispatch is the default and only way functions work.

<comment><USER8> > Lisps, of course support multimethods, which is great. There are some down > sides, though. They are opt-in (defmethod) and tend to have a significant > performance hit

Worse than faking it in (say) C++ using the visitor pattern?

</comment></comment></comment></comment><comment><USER9> The claim that "an object is a set of functions that operate on implied data elements" has a strange corollary because of how in modern OO languages like Java or C#, there is no syntax or popular naming convention to tell the difference between a data structure and an Object. For example, in Java, a LinkedList object is actually not a linked list, it is a set of functions that operate on an implied linked list. If the system needed direct access to the data for whatever reason, we'd need to explicitly have a LinkedList data structure object that only contained the data (the values and their pointers), as well as a second class, the LinkedListOperator, that contains all the functions (add, first, etc.). Likewise, in the author's examples, there'd be a Square class and a SquareOperator class.

I was going to say that Haskell addresses this by putting values in data types and behaviors in "type classes", but then I remembered that functions can be values... which is now making me think that the reality is probably more abstract or complex than the author here is letting on.

<comment><USER3> In a purely oop language, data structures exist as an implementation detail, but you can never access them directly (as in, bypassing the object interface). That's by design.

<comment><USER9> I get that in your application, you may want to keep a linked list behind its interface 90% of the time. However, considering your system as a whole, at some point you may want to take that linked list data and write it to a database, in which case the cleanest thing is to bypass the interface and extract the "data structure object" so to speak and deal with it in a database-related object, rather than encumbering your LinkedList object with database behaviors.

<comment><USER10> This is a violation of OOP. Instead, consider methods that produce and consume a serialized representation of the data instead.

Things like Java serialization and Python pickle attempt to do what you say and are considered failures (or at least security risks) because they allow a third party to act on object implementation internals.

Security aside, a denormalized representation of data could be different than the implementation specific representation that's encapsulated inside an object.

<comment><USER11> But this is partly a self-made problem, because in this OOP model you have decided that the internal representation of your data is to be hidden and therefore the data is only accessible via the provided interface.

In practice, it is debatable how often that is helpful when you're implementing generic data structures. An alternative is to specify the representation explicitly and provide a set of functions designed to work with it, but also to allow direct access by other functions when that is useful.

You can still build a layer of more abstract interfaces on top and write more generic algorithms in terms of those interfaces rather than any specific concrete representation, as for example Haskell's typeclass system does.

<comment><USER10> >An alternative is to specify the representation explicitly and provide a set of functions designed to work with it, but also to allow direct access by other functions when that is useful.

I don't see that as an alternative. I consider this natural OOP. You don't lose anything by strictly enforcing the encapsulation because you can always explicitly provide low level methods into the data structures. Conversely, you lose all safety when you open up encapsulation. The method API of an object is the contract it provides. If you go around that contract it's much harder to make safe implementation changes.

Because of this, low level access should be opt in, in the way you describe.

<comment><USER11> _You don 't lose anything by strictly enforcing the encapsulation because you can always explicitly provide low level methods into the data structures._

But then you're not really gaining anything either, unless perhaps you have some mechanism to enforce that the low-level access should only be used in specific circumstances when it is deliberately intended. It's like writing classes that have a few data members, but then writing direct get and set accessors for each of them anyway. There's no more complicated invariant that you're enforcing at that point, and without any non-trivial invariants to be enforced, the whole argument for encapsulation and data hiding becomes moot.

 _Conversely, you lose all safety when you open up encapsulation. The method API of an object is the contract it provides._

Do you always need that safety, though? If your data is defined to be stored in a certain representation, and direct access to that underlying representation in that format is available if needed, isn't that representation now just another part of the contract? Again, you're balancing two competing priorities: is there some invariant to be enforced that is sufficiently complicated for data hiding to be a useful safeguard, and is it useful to interact efficiently with, or make safe assumptions about performance based on, the true data representation?

Which one is the more important consideration must surely depend on how complicated your representation and any related invariants are. Being able to pattern match against values of some relatively simple algebraic data type can be very useful, for example. On the other hand, it's not much fun to accidentally corrupt the super-efficient look-up structure at the heart of your whole system that now uses a complicated set of hash tables and the odd Bloom filter internally after someone spent three weeks optimising it for a 50% speed boost.

<comment><USER12> You can change the internal representation while doing transformations in the getter to preserve compatibility.

With collections, you can export contents through an Iterable, or to Array, or any number of other strategies, without coupling the consumer to your internal representation.

<comment><USER11> Of course, but what I am questioning here is how often we really do change internal representations of simple data structures. The theoretical benefit of hiding every representation behind an interface is clear, but any abstraction also has a potential cost if it creates a barrier to doing something useful and/or becomes leaky.

You can still provide standardised interfaces for things like iteration along with a data structure even if you choose to expose the specific representation, so I am not sure how strong an argument your second point makes. Depending on the situation, you may find your consumer is implicitly coupled to the true representation anyway, perhaps because it inadvertently relies on values being iterated in sorted order or insertion order or because it assumes certain performance characteristics even if these things are not strictly part of the documented interface. More than once in programming history, even standard libraries of popular programming languages have been updated to guarantee some behaviour that had been reliable in practice but was never actually part of the original specification.

<comment><USER13> My perspective is from a heavy Java background.

By using the standardised interfaces for everything you can change the implementation without changing how you work on it.

For example, my service that stores a collection in a database. I could write my service so that it takes in a Collection, rather than an ArrayList, because then anyone using it can pass in a Set (no duplicates), CopyOnWriteArrayList, TreeSet (ordered set).

By hiding internals and using the interface, I can pick the abstraction I need and give more freedom to those using my classes.

Another example. Once Project Valhalla and Value types come in, LinkedList might be changed to use value types for Nodes. Lets say I've tightly coupled my code to the implementation of LinkedList. This could potentially break my code.

<comment><USER11> And there is nothing wrong with writing generic code like that! Just because you _can_ access the specific representation of the underlying data, that does not mean you have to or would do so routinely. In languages that do tend to expose simple data structures directly, it is still normal to provide standardised tools for accessing and manipulating them, and most of the time that is probably still how you would interact with them.

Regarding your second example, if you are working with an explicit representation then you simply would not make a breaking change like that. Instead you would create a new data structure with the new representation, which other code can then choose to use instead if it wants to. Again, nothing about this prevents both versions from also providing equivalent functions to access them in the same way where that makes sense or writing other code in terms of those functions rather than tied directly to the specific implementation.

</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER14> The first set of points:

> Classes make functions visible while keeping data implied. Data structures > make data visible while keeping functions implied. > Classes make it easy to > add types but hard to add functions. Data structures make it easy to add > functions but hard to add types.

is known as the Expression Problem [https://en.wikipedia.org/wiki/Expression_problem](https://en.wikipedia.org/wiki/Expression_problem).

The last point:

> Data Structures expose callers to recompilation and redeployment. Classes > isolate callers from recompilation and redeployment.

is only somewhat true. I _suspect_ it would be more accurate to say that it's a matter of indirection: static dispatch isolates callers from recompilation; static dispatch exposes callers to recompilation; calling a function pointer isolates callers from recompilation; calling a function directly exposes callers to recompilation. (All of this in statically typed languages.) Though this isn't my area of expertise. Perhaps someone else knows more? [Edit: sounds like these "expose" cases often don't cause recompilation either.]

<comment><USER15> Regarding the claim ... > Data Structures expose callers to recompilation and redeployment. Classes isolate callers from recompilation and redeployment.

... most projects (maybe all?) I've worked on in 20+ years deployed a full set of new bits upon release, rather than trying to differentiate at the level of which source code files were and were not touched.

So this strikes me as a carryover from many years ago when working on large C++ projects with slow compile times was even more painful than it is today.

Any counterpoints?

<comment><USER16> C++ is still painfully slow to compile, and seems to get slower every year.

<comment><USER17> > C++ is still painfully slow to compile, and seems to get slower every year.

oh come on. I can get a full build of qt5's main libraries (core, gui, widgets, network, xml, etc) in 15 minutes on my laptop. It took an hour a few years ago. Compilers are getting faster all the time.

</comment></comment></comment></comment><comment><USER18> >OK, OK. I get it. The functions that operate on the data structure are not specified by the data structure but the existence of the data structure implies that some operations must exist.

This reminds me of Linus's quote:

"

I'd also like to point out that unlike every single horror I've ever witnessed when looking closer at SCM products, git actually has a simple design, with stable and reasonably well-documented data structures. In fact, I'm a huge proponent of designing your code around the data, rather than the other way around, and I think it's one of the reasons git has been fairly successful ( _).

(_) I will, in fact, claim that the difference between a bad programmer and a good one is whether he considers his code or his data structures more important. Bad programmers worry about the code. Good programmers worry about data structures and their relationships.

"

[https://lwn.net/Articles/193245/](https://lwn.net/Articles/193245/)

<comment><USER19> I may need to reread it, but wasn't one of the key arguments in Parnas' "On the Criteria To Be Used in Decomposing Systems into Modules" that by modeling around data we fall into the trap of writing code that's "temporally" dependent?

</comment></comment><comment><USER20> This conversation reminds me of [https://en.wikipedia.org/wiki/Expression_problem](https://en.wikipedia.org/wiki/Expression_problem) .

I don't understand: "but the existence of the data structure implies that some operations must exist."

Grounding it out to a specific data structure, the existence of `List` implies that e.g. `sort` exists?

That direction makes less sense than `sort` implies the existence of e.g. `List`(something to be sorted).

<comment><USER21> _the existence of `List` implies that e.g. `sort` exists?_

The existence of List implies that operations must exist to insert an element in a list, access to elements in a list, find out the size of the list, etc.

Edit: BTW 'implies' is the the magic word in the text. It's what creates all the appearance of meaning. Try to replace it what something else. Now I remember why I disliked Plato so much.

<comment><USER20> I thought about using `[]`or `indexOf` as examples of operations, but my question still remains: what is implicit about it? It's part of the public interface of `List`.

Not at all like the private members of an object, which I think was the analogy being made.

<comment><USER22> Those aren't implicit because the "public interface" is the Object List, not the Data Structure List.

        struct list {
          float node;
          struct list *next;
        }

Above is the data structure; it implies operations. Below is an interface (class, in the article); it implies data.

        #define LIST_H

        float index(struct list *ls, int i);
        int find(struct list *ls, float x);
        void sort(struct list *ls);

</comment></comment></comment></comment><comment><USER23> Maybe a little tangential but it immediately came to my mind Alan Perli's quote: "It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures." I think I first heard this from Rich Hickey and made so much sense.

</comment><comment><USER24> What the author calls "objects" (or "classes") is really often just "interfaces".

> An Object is a set of functions that operate upon implied data elements

If this is replaced with:

> An Interface is a set of functions, often operate upon implied some implied > data elements (but not necessary).

Everything in the article will probably be less confusing.

</comment><comment><USER25> And while the discussion takes place and the debate rages between classes vs. data structures, there's some poor analyst or data scientist who just needs access to the damned data to load it into a pandas data frame to do things that those designing the objects and data structures never dreamed of in the first place...

</comment><comment><USER26> Interesting read. What immediately sprung to my mind was Rust's Trait system which sort of manages to give you the best of both worlds. With Traits you can implement common behaviour/functions for multiple datastructures.

When I started using Rust I wasn't used at all to seperate data and behaviour that strictly, but it makes sense. OOP paradigms were still hardwired in my head so the hardest part was actually _wanting_ to do it in that decoupled way. Something about a car object that has wheel objects and a car.drive() function gives you a good feeling as a programmer, but sometimes it is more effective to stay with the data structure and describe the car as a struct of vectors which implement a _Driveable_ trait..

</comment><comment><USER27> Thinking about client-server architecture (for example, a database) can clarify things.

Encapsulation means you never have the canonical data. The server is the system of record. You can get data back in response to queries, perhaps even a full data dump, but it's a snapshot. You can also send commands to mutate data on the server. Typical applications aren't allowed to do a complete replacement (restoring from backup).

On the other hand, data is better thought of as what's going over the network. Messages consist of data. Encapsulation is almost meaningless; if you want to keep something private from the receiver, don't include it in the message in the first place (or use encryption, maybe). Anyone reading the data has to be able to understand the format, or at least, ignore what they don't understand.

In the degenerate case where the caller and implementation live within the same process, the same types often get used both for message transfer (in function arguments and return values) and storage. There is widespread "cheating" for performance reasons, and it can get confusing. For a transient process, it might not make sense to think in these terms at all. (Traditional Smalltalk used _persistent_ images and client-server style encapsulation makes somewhat more sense there.)

You can also "cheat" by using the same schema for data transfer and storage, or having a trivial mapping between them. This can introduce unnecessary coupling, but there are systems where it works. (Consider that you can make a full clone of a git repo and it doesn't encapsulate any data.)

</comment><comment><USER28> I like the shapes problem because I actually encountered it and it made me think.

I'm not sure about the switch approach described in the post:

      function area(shape)
        switch shape.type
          case "square": return shape.side ** 2
          case "circle": return 2 * PI * shape.radius
          case "triangle": return ...
          case "segment": return 0
          case "polygon": return ...
          ...
          case "oval": return ...

You can have a lot of cases, some of them requiring non trivial code... Eventually you write a function for each case and it's more work than adding a method for each shape because you still need to write the switch...

Classes seem work better than structures here.

But then you want to handle intersections

The switch approach doesn't seem realistic:

      function intersection(shapeA, shapeB)
        if(shapeA.type == "circle" AND shapeB.type == "circle")...
        if(shapeA.type == "circle" AND shapeB.type == "square")...
        if(shapeA.type == "square" AND shapeB.type == "circle")...
        ...//uh oh you have nShapes**2 cases to handle

But java classes or not better: where do you define Circle-Square intersection? In Circle? In Square?

Even with multiple dispatch the solution is not ideal. You now have some things related to Circle (area, perimeter...) in the Circle.blub file, and intersection(Circle, Circle) wich only works with Circles is now in intersections.blub...

I don't see a good solution and sometimes I feel like the problem is more with our tools (code in text files) rather than programming paradigms

<comment><USER4> I have to admit I don't quite understand your issue. To me it seems like you've used a lot of OOP and cannot befriend the idea that the data structure (e.g. "Circle" in file GeometryTypes.blub) and operations that are performed with it (e.g. collisions in "CollisionDetection.blub") are completely separate. There should be no discussion whether the circle type and collision belong in the same file, while combinations are in some other file. Think of it like this: if you're going to add 3d rendering of circles, will you put that in Circle.blub together with collision detection? Wouldn't you rather add it to 3DRenderer.blub?

That said, ultimately it doesn't really matter. If you're going to implement collision detection like this, then yes, you will have a combinatorial explosion. This is not a language issue. Switching from Java to some other language with a different form of dispatch will not save you from implementing a lot of algorithms when adding bezier curves into the mix.

The practical approach is reduce the problem to a common case, e.g. to turn the collision shapes into a set of triangles first, and then perform triangle- triangle collision detection.

</comment></comment><comment><USER29> The dependency discussion is wrong. Changing code of a function does not lead to recompilation of callers in most static languages. So if one change circlePerimeter, only that has to be recompiled. But if one changes data structure, then the callers has to recompiled. But this is also true for objects. In C++ changing data typically leads to recompilation of both implicit and explicit data structures. Essentially objects and data structures behaves the same.

<comment><USER30> > Changing code of a function does not lead to recompilation of callers in > most static languages.

I don't know how we're quantifying so as to assess "most", but at least in some popular static languages there are circumstances (most notably inline functions) where callers are likely to be recompiled and circumstances (dynamic loading) where they clearly won't be.

> But if one changes data structure, then the callers has to recompiled.

Only if you're changing parts of the data structure that are visible to callers. For instance, if your API operates on opaque handles you can change the underlying data structure however you'd like without recompiling the caller.

</comment></comment><comment><USER31> _Why does every software example always involve shapes?_

Because they allow us to avoid discussing the complications that arise when entities have lifetimes, over which, at different stages, different operations are meaningful.

<comment><USER32> Because it's one of the very few cases where class inheritance is an elegant solution.

</comment></comment><comment><USER33> A class is fundamentally about implementing object semantics. This simply means everything (eg. all objects) are an instance of some class. It has methods which can be used to operate or communicate with other objects or itself.

Data-structures are put most simply as ways of organizing data. The organization of the data implies a specific layout--a way of representing your data as a table of integers, ie. in RAM.

After reading the article, I don't see a meaningful distinction between objects and data structures. A data structure can be represented as an object, especially in OOP languages where it _must_ be.

A general class doesn't necessarily lay out its data in any particular way-- which allows abstraction over the data representation of the class.

However, some classes are made which are designed in a manner which guarantees a certain data layout. std::vector with its contiguous memory requirement comes to mind.

To add to this, the c++ conception of a "concept" or haskell's concept of a "typeclass", or even a generic class, is really what this article is talking about. Or even Java or Go's interfaces. There is absolutely no way to guarantee a specific data structure through an interface, typeclass, or concept, since they fundementally do not mention their data representation at all.

</comment><comment><USER34> I enjoy the authors "question/answer" style of writing. I often find myself asking questions just like this when reading an article, and find that when the author isn't "question focused" they never get answered. It seems that when the entire writing style pivots on the idea, the author forces themselves to consider more Q's to pad out the content and, incidentally or otherwise, provide more A's.

<comment><USER35> I find it smug and insufferable, like someone on tumblr lecturing you about demisexual marxist theory or something.

</comment></comment><comment><USER36> This doesn't make sense to me: "Right. Now consider the area function. Its going to have a switch statement in it, isn't it?"

Perhaps I am nitpicking, or perhaps I am reading this wrong, but I would not design the square data structure to have a perimeter function. The square data structure should just expose the data that describes a square (length, width). Adding higher abstractions (perimeter, etc) on top of the data structure only serves to create the trumped up problem later described in the dialog. The perimeter method should be defined in the Square class, where perhaps a "StraightLinesOnlyPolygonMixin" could define the perimeter method.

In general, I cannot see why a Data Structure would define computational methods. You are tightly coupling logic to the underlying data source, which is wrong when that logic obviously could apply to any underlying data source (I don't care if my square is backed by RDB, S3, a hardcoded instance, etc) The perimeter method, and probably the Square class, should be the same.

<comment><USER37> You are getting it wrong. Data structures do not own functions, instead they are passed to functions. So you have shapes and somewhere else you have perimeter function which has switch statement to determine the algorithm of calculation based on the type of the structure.

<comment><USER36> Ah, and what owns these functions?

And more pressingly, why would you ever pass a data structure to a function that had more than one algorithm to compute a result? The data structure (or perhaps some intermediary (an adapter?)) should own the algorithm within a function that computes only on that data structure. This ensures that all methods associated with your data structure are obviously and explicitly associated (in a single file, class, whatever). The alternative, as outlined in the dialog, is to spread a bunch of switches all around your code. Given these two possibilities, why would one choose to place switches in disparate places throughout your code?

<comment><USER11> _Given these two possibilities, why would one choose to place switches in disparate places throughout your code?_

You are touching on something called the "expression problem". You might be interested in reading some commentary about it. There is an inherent decision to be made any time you have many algorithms each operating on many data types. In most programming models, you have to choose between grouping your code based on your data types (but then any new algorithm needs to be implemented on each data type) or based on your algorithms (but then any new data type needs to be supported by a new case in each algorithm). Neither is the "right answer". You fundamentally have a two-dimensional system here, and you need to decide which axis you are going to prioritise in your design.

<comment><USER36> Thanks. I will look into this. I would like to see examples that obviously require algorithm-grouping or type-grouping, as in my experience, algorithm- grouping has always lead to headaches.

I think I have encountered this issue in the past but was turned of by the lack of formality in the discussion. I wish there was more academic, concrete discussion of these issues, because I feel that what I am doing now (informal discussion) likely has many holes.

</comment></comment></comment></comment></comment><comment> steve-chavez > Since the database schema is a compromise of all the various applications, > that schema will not conform to the object model of any particular > application.

Here it jumps to objects instead of database VIEWs, that can be tailored for each application. There's no need for complex object models when you embrace the db and you don't treat it as a dumb store.

</comment><comment><USER38> " _No, ORMs extract the data that our business objects operate upon. That data is contained in a data structure loaded by the ORM._ "

Technically, ORMs are a set of waldos that you operate inside a glove box in order to manipulate the data in the DB without getting DB cooties on you.

</comment><comment><USER39> Classes vs Data Structures, or maybe Objects vs Data Structures, or maybe Classes vs Objects, or maybe Data vs Data Structures, or maybe Data vs State, or maybe Classes vs Types, or maybe OOP vs FP, or maybe I don't know what I'm talking about...

</comment><comment><USER40> Seems to me that with the definitions given, structures and objects aren't opposites, they're corollaries.

A database table is both a data structure and a collection of functions for accessing/manipulating it (SQL). An ORM maps between the "Object Oriented" objects and the "Relational" objects that are tables.

Interesting the author thinks about the the api exposed by a table as the "data structure" itself rather than an object. Pragmatically, we tend to refer to the "objects" at the lower level of abstraction as data structures. Is [...] a function that defines an array, or the array itself?

</comment><comment><USER41> Am I the only one who has trouble with the dialog form?

<comment><USER42> No. The way the text is written obfuscates the point the text is trying to make, IMO.

<comment><USER43> I personally found the dialogue form amazing and made the article very understandable.

</comment></comment></comment><comment><USER44> This is really hard to follow and I'm not sure I'm understanding it the way he intended.

Correct me if I'm wrong, but he seems to be saying that, to avoid breaking consumers of your library often by changing the implementation, hide the implementation details behind classes, right?

This seems to be a common reaction to someone who experiments with the "freedom of functional programming" where that freedom means operating on and returning raw data structures that OOP usually hides behind private variables.

That's still bad practice, even in code that heavily uses FP, and good code usually mixes FP and OOP properly, so that you're given functions when you're meant to have functions, and data when you're meant to have data. This is how I've been writing JavaScript for a few years now, and it's not how I've seen Java or Clojure usually written.

<comment><USER45> I don't think he's exactly advising any particular action. Rather, data structures and objects tend to be badly conflated, and there's a lot of value in clarifying the distinction between them. You'll use each in different circumstances, for different reasons, by weighing the needs of the system against the design tools at your disposal.

In Rust, we keep the same distinction by modeling data structures as structs and enums, and modeling the "object" side by traits (whether static- or dynamic-dispatch). Traits decouple a consumer from the particular data and emphasize a behavioral contract, allowing any data structure to implement the desired behavior.

<comment><USER44> So basically mixins, right? Those were hard to use correctly in Ruby, because you might have multiple whose behavior clash because they can access the same data and were not written with each other in mind. I wonder how Rust solves that.

<comment><USER45> Not quite. A mixin is a piece of code written once and transcluded into another module. Traits are more related to OOP interfaces: every type implements one in its own way. The difference with interfaces is that traits can be implemented separately from the definition of the underlying data type, which clarifies the distinction between inherent operations on a specific data structure, and derived operations that bind it to a more general contract of use.

</comment></comment></comment></comment><comment><USER46> Was surprised how Uncle Bob getting better at trolling these days. He's been provoking, but somewhere in recent years he turned himself to a troll. (Or he's just talking to his audiences, who aren't HN readers.)

</comment><comment><USER47> very interesting and worthwhile! Data has gravity; and data dependancies are more costly than code dependancies, are two lines that are current.

Objects may possibly have broader uses that what is described here ("business data applications") but within the definition given, the description of Object and operations on object make a lot of sense. This post is worth re-reading a few times.

</comment><comment><USER48> Whenever I hear "Socratic dialog", I reach for my revolver. Is there any other form of teaching so irritating and patronising? You might have a brilliant store of insight to impart, but if you insist on trying to do so via a twee, affected and unbelievable conversation with a Mary Sue wise professor, I'm going to write you off as insufferable before the fawning moron you have as proxy for your audience utters their first "Oh, wow! So you mean that straw- man you just put in my mouth _isn 't_ true?"

<comment><USER49> The only thing more annoying is when people ape Why's (Poignant) Guide to Ruby and you have to follow the adventures of some tedious otter as it meets the rabbit people who ultimately explain pointers in a way which takes a thousand too many words.

<comment><USER50> Have you ever come across anything that explains why pointers are hard for some people?

I find it difficult to explain pointers to people because I don't understand what they are missing. I could use some help understanding their lack of understanding.

When they don't get "indirect reference to the address of a data structure or object in memory", I'm stuck on how to proceed. Pointing people to the very elegant treatment of this topic in the old K&R doesn't always do the trick. Somehow.

<comment><USER51> I don't think I understand pointers. Maybe we can help each other. My mental model of pointers is a map: lat/long identify the object of interest (the local coffee shop), but not what is interesting about it (their menu and hours).

<comment><USER50> Hmmm. Interesting. I'm going to have to roll that around in my brain for a day-or-so to see if I can make that compute for me. (Which means I may be back here in a day to check back in!)

Maybe it's because I started in assembly language, but to me, data exists at an address in memory. Or starting at an address in memory. That data might be on integer, a float, a character, the beginning of a string, the head of an object/data-struct, OR an address of data somewhere else (which may be any of the above again). Pointers, to me, are simply an address of an address of a data thingie.

Why would you want to use these? One reason is that pushing large data-objects back-and-forth across function calls is expensive (pointers are usually just 32-bit or 64-bit numbers). Another is that one can have a pool of resources (think polygons in a large 3d scene), that are marked "used" or "unused". This gets a large performance boost from not having to do the whole malloc/free thing on lots and lots of small objects. Another (this is related to the first), the function can receive a data-structure, and modify it (side effects!) without having to copy it and pass the modified copy back.

I'm intrigued by your mental model. Having not thought it through - it seems as if lat/long is appropriate, but maybe even the idea that it is a coffee shop that you will find there is undetermined. (That is: the fact that it is a coffee shop is one of the things that is interesting about it, like the menu and hours. Again, I need to think this through).

Thanks!

<comment><USER52> Note that your model is also an abstraction. Modern architectures move data around between a variety of memory locations (and store it in multiple locations) which are all addressed via the pointer 'transparently'. It's not really a memory address anymore and hasn't been for some time.

That's not to say your model is bad, it's the same one I have in my head. But it's no more 'real' than coordinates or library cards or P.O. Box number.

<comment><USER42> Isn't it still the model that is exposed to the programmer, even though internally all kinds of things are going on to make it all go faster? For example, nowadays many/most processors have separate caches for instructions and data, meaning that they strictly speaking don't conform to the Von Neumann architecture. But the programmer doesn't see the different caches, ideally doesn't even see the cache at all.

It's like the execution model, where processors do a lot of out-of-order execution, but do a lot of work so they can present a model to the programmer as if everything happens in-order.

<comment><USER52> That depends on the architecture, the os, the compiler & the runtime.

Part of the confusion in teaching pointers (I think) is that we act like they are a lower level abstraction than they are (because they used to be). On modern commodity hardware with mainstream languages pointers have very little to do with memory addresses. Accessing memory via them will not happen in constant time, they may or may not perform better when used, even if the language doesn't copy them on use the OS or processor might etc.

I just find when I try to teach people the memory address model of pointers there are so many exceptions that the model isn't helpful. Like the OP I struggle with an alternative.

</comment></comment></comment></comment></comment></comment></comment></comment><comment><USER53> Not every language is class-based...

</comment><comment><USER54> When Uncle Bob discovers subclasses, friends, decorators, and mixins, his mind will be blown.</comment>


Creatures: Artificial life software agents (1997 paper on AI game) - <AUTHOR> http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.18.9182&rep=rep1&type=pdf <comment><AUTHOR> So, does current AI research have access to a similar artificial environment playground simulating:

* body biochemistry

* genetics / artificial evolution

* perceptual systems

* motivations / drives

* the interplay of different brain lobes

* environmental processes like weather

Can't think of one.. Has AL+AI research disappeared? The success with OpenAI DOTA is all great, but is DOTA (with its clearly defined pragmatic goal states) really more interesting for AI research than an autonomous artificial agent?

Afaik this game saw one of the few applications of multi-layer perceptrons / neural networks in commercial games.</comment>


State of the art of random double generation - <AUTHOR> http://www.blahonga.org/2015/04/state-of-art-of-random-double-generation.html

<comment><USER2> This 1:2:1 distribution is the right sort of behavior for a double-precision random number generator (what the standard says notwithstanding). It's what you get if you throw a uniform random dart at the real line and round it to the nearest floating point number.

Also, a <= x <= b is really the right way for uniform floating point ranges to be, with half-probability of the edges getting selected. The API of returning [0, 1) is pretty horrid, because then when somebody uses that to generate [1, 2), by doing rand01() + 1.0, they actually create the possibility of generating 2, because (1-2^-53) + 1 rounds up to 2. (That's just like the rounding that happens when generating to [2^52, 2^52+2].)

If you want a <= x < b, getting that for practical purposes could be relatively simple: compute rand01() * (b - a) + a, and if the output is >= b, then return a. That works wonderfully if rand01() behaves like randint(2^53) / 2.0^53. It's a little suboptimal if rand01() is implemented something like randint(2^64) / 2.0^64, because it creates a weird little density spike at the bottom for contrived ranges such as [2.0^-30, 1 + 2.0^-30), but if you're getting that anal you'd also worry about the round-to-even behavior of computing rand01() + 1.0.

<comment><USER3> _" It's what you get if you throw a uniform random dart at the real line and round it to the nearest floating point number."_

Only when you throw the dart, repeat until you are in the target interval, and then look for the nearest representable number. If you throw the dart, look for the nearest representable number and repeat until that number is in the interval, you get something different.

Worse, neither approach gives you a uniform distribution in the general case. The hypothetical uniform dart is as likely to land between 1 and 2 as it is to land between 2 and 3, but there are more representable numbers in the first range than in the second.

I also think your _rand01() + 1.0_ example is flawed. It is just because floating point is hard that this kind of functionality ends up in a standard library.

<comment><USER2> > Only when you throw the dart, repeat until you are in the target interval, > and then look for the nearest representable number.

Yeah, when you throw your dart at the target interval.

> If you throw the dart, look for the nearest representable number and repeat > until that number is in the interval, you get something different.

I don't know why you'd want to throw a uniform dart at some other, larger interval, before culling it down. You can't throw a uniform random dart at the entire real line. I think what you're describing gives undue representation to the edges -- you wouldn't use those sampling points with those weightings to integrate a function, but you might use the trapezoid method.

> The hypothetical uniform dart is as likely to land between 1 and 2 as it is > to land between 2 and 3, but there are more representable numbers in the > first range than in the second.

That's a fact of life.

</comment></comment></comment><comment><USER4> At first, I thought trying to sample "uniformly" from a discrete non- homogeneous set of real numbers was just mathematically nonsense, but there's actually a pretty elegant generalization:

Basically, the probability of picking any particular floating-point value x should be proportional to the distance from x to the next largest representable number (with zero probability of choosing the largest floating- point number). This has the property that for any two floating-point numbers a and b, the probability of sampling a value in the interval [a, b) is proportional to b - a, which is the same as the defining property of the usual uniform distribution on real numbers, just with some additional restrictions.

</comment><comment><USER5> It's no better in Java. A fairly literal translation of the code [1], using the new Random::doubles method [2], gets counts like so:

      166808
      332743
      500449

If anything, this is even weirder than the C++ results. :rage1:

The doubles method makes each value "as if it's the result of calling the following method with the origin and bound':

      double nextDouble(double origin, double bound) {
        double r = nextDouble();
        r = r * (bound - origin) + origin;
        if (r >= bound) // correct for rounding
          r = Math.nextDown(bound);
        return r;
      }

Which is the naive approach that Artur has been struggling against.

[1] [https://bitbucket.org/snippets/twic/qqEe](https://bitbucket.org/snippets/twic/qqEe)

[2] [https://docs.oracle.com/javase/8/docs/api/java/util/Random.h...](https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#doubles- long-double-double-)

</comment><comment><USER6> I guess this could be related to my question I asked some time ago on SO: [http://stackoverflow.com/questions/25668600/is-1-0-a-valid-o...](http://stackoverflow.com/questions/25668600/is-1-0-a-valid- output-from-stdgenerate-canonical)

</comment><comment><USER7> A related question:

Is there any efficient way to generate a random number in a range w.r.t. the amount of entropy used? The way I know (generate a random number, if it's in the top incomplete section regenerate until it isn't, modulo the width of the range, add the starting value - there are some fencepost errors here but you get the idea) is really inefficient in the case of, for example, you want a number between zero and half the range + 1 (so, for example, if you have an 8-bit RNG and you want numbers between 0-128, inclusive.)

You end up using, on average, 8*(1/(1-127/256)) ~= 15.9 bits of entropy per call, whereas you only "need" to use log2(129) ~= 7.0 bits of entropy per call.

<comment> mark-r Sometimes you can generate the random numbers in batches to get better efficiency.

For your example, you can combine 3 random 8-bit values into a 24 bit value. You still only get 3 outputs, but you can use all the random values up to 7 * (129^3) - you only need regenerate random numbers 10% of the time, rather than 49%. 60 bits does even better, giving you 8 outputs and requiring regeneration only 0.2% of the time.

<comment><USER7> Nice.

A pity it requires knowing sizes in advance. I wonder... Could you do something similar "afterwards"?

<comment> mark-r Sure you can, I used a short program myself to calculate the best case outcomes. The question is whether it would be worth the bother. Usually the range you request is much smaller than the range of your random number generator, so the number of regenerations required are nowhere near the worst case - and the cost of generating a random number isn't enough to get worried about.

</comment></comment></comment></comment><comment><USER8> What good is the standard implementation if the gcc guy responds with WONTFIX?

</comment><comment><USER3> Root of the problem seems to be that the standard gives pseudo code for generate_canonical (paragraph 126.96.36.199 in my unofficial version) that implementations must follow that, when translated straightforwardly into C, gives results that are inconsistent with the textual description of the function.

See [http://stackoverflow.com/a/25669510](http://stackoverflow.com/a/25669510)

<comment><USER9> Language-lawyers-no-oxygen-astronauts (1) strike again.

Producing quality random floating point numbers, fast, is a solved problem (maybe even since the times of John von Neumann) but the astronauts would then have to come to the Earth and not just invent the wrong code attempting to use the the latest features of the standard. The direction should be the opposite: starting from the known and proper solutions, see how they can be (if they need to be) standardized.

The standard that standardizes "something" while not knowing how the problem is actually solved in practice is actually dangerous.

1) [http://www.joelonsoftware.com/articles/fog0000000018.html](http://www.joelonsoftware.com/articles/fog0000000018.html)

<comment><USER10> Author of the blog post following the sudden surge of traffic here.

> Producing quality random floating point numbers, fast, is a solved problem

Is it? Do you have any reference I can read?

Everything I've found is obviously flawed on the level of `(rand() % 1000)/1000.0`. I don't actually care about the C++ facilities that I'm discussing in that post. I just hoped that they would be a good path to follow to find one good source that discusses the various trade-offs between mapping a set of random integers (or a stream of bits, or whatever) to floating points. I've seen serious peer reviewed papers that just randomize the bits of the exponent and mantissa and call that random or papers that do what I've tried to do (which has its flaws) - count the number of representable, uniformly spaced, floating point numbers between `from` and `to` but then generate their random numbers with `random() % count`, which is like restoring the Mona Lisa with crayons.

So I'm completely serious. I'm desperate for a good source, where can I find it?

<comment><USER11> I get the impression that it's indeed not a solved problem, and even implementations that do not have to follow standards like C++ get it wrong. I recently submitted this to Hackernews, which is a nice treatment of the problems:

[http://mumble.net/~campbell/2014/04/28/uniform-random- float](http://mumble.net/~campbell/2014/04/28/uniform-random-float)?

<comment><USER10> I actually got the link to his code yesterday and it's eerily close to what I wrote a few months ago, but I rejected that approach because I didn't like that any of the numbers in [0.5,1.0) were so much more likely to be returned than 0.0. This gives the highest possible entropy and all numbers representable by floating points in that range can be returned, but the trade- off is that certain values will be returned vastly much more often than others. It's this discussion of trade-offs that I'm actually missing.

I don't feel competent enough to write that paper/article/rant about the trade-offs myself, I barely understand math and randomness, but I'm getting tired of all the libraries out there that say "uniform[1] random[2] floating points[3] [1] - not actually uniform [2] - not actually random [3] - terms and conditions apply, YMMV, not valid where invalid".

<comment><USER12> What do you mean when you say you don't like that some numbers are returned more often than others? This seems completely inevitable for a uniform distribution because floating point numbers don't have a uniform density across the real line.

Only if you choose a range like [1,2] with a uniform density of floating point numbers you will see all floating point numbers in the interval - except both bounds of course - with equal probability.

You would have to not return some floating point numbers ever to see all returned floating point numbers in the interval with equal probability but that of course hardly qualifies as a uniform distribution if some perfectly valid floating point numbers will never occur.

<comment><USER2> It totally qualifies as a uniform distribution. Is it the case that generating [1, 2) generates a uniform distribution, but subtracting 1 from that does not produce a uniform distribution?</comment></comment></comment></comment></comment></comment></comment>


Launch HN: Point (YC W19) – First Debit Card with Points - <AUTHOR> Hi HN community,
We're Patrick, Kenan, and Sid, the founders of Point (https://trypointbank.com), a consumer digital bank focused on rewards. After being fed up with the poor customer experience and tactics of traditional banks, we did some digging into why we put up with our own subpar banks. We've discovered that the way most people end up with their current bank is by default (ex: parents set it up for them), rather than by choice. The complete opposite was the case for credit cards; credit cards were actually chosen based on their qualities.
We began to wonder why a solution that combined the rewards and benefits of a credit card, with the simplicity of a bank account didn't exist. After extensive research and testing of various existing products, we determined that everything came up short for our personal needs. That was the problem.
Whether it was simply the lack of a clean mobile user experience, or rewards that were relevant, nothing managed to fit the bill. Since banks are a fundamental part of our everyday modern lives, we shouldn't have to settle for a less-than-stellar experience just because that's the current standard. That's when we realized, we don't have to settle. This was an exciting enough realization for us all to quit our day jobs as product managers, designers, and engineers. We decided we needed to create a revolutionary bank.
In order to solve this problem, we created a new-and-improved debit card. We are focusing our efforts on debit because it is currently the most popular payment method. Although debit is the preferred method, in the real world, there is little incentive to use one over the perks offered by credit cards. This unfortunately leads the majority of the dissatisfied group to settle for credit cards, with their offer of limited perks that typically come hand-in-hand with unavoidable debt.
Our business model is sustainable because we are partnered with a smaller regional bank and don't have the hefty over head of a branch network. The reason we don't see larger banks offering debit cards with rewards is because of the "Durbin Act"; a federal mandate which slashed interchange margins of banks with more than $10 billion in deposits. This was done in order to protect consumers and merchants from increasing and predatory prices that banks were trying to instill.
If successful in our mission we hope to keep the up and comers out of un-necessary credit cards and raise the standards of user experience for banks. There is no reason why dealing with your bank should be as dreadful as the DMV.
We look forward to hearing your thoughts on what we are building and are open to any and all suggestions. Feel free to drop us a line at email@example.com and check out our waitlist on our landing page. <comment><USER2> Ok, so here's my take on most new debit card and checking account offerings.

Things I do not care about:

* points and loyalty programs * measly 2% APR * tracking my spending habits * how the card looks

Things I do care about:

* a card that works and gets accepted (no spurious declines because the bank thought so) * a card that works with Apple Pay (hi Revolut) * no nags, upsells, emojis, animated GIFs, or other teenager stuff (hi Revolut) * do not waste my time * have secure online access (as in, do not use SMS for 2-factor auth, because really) * ability to issue new cards quickly * ability to change my address quickly, even if I move to a different country * whether the company will disappear and/or steal my money (don't laugh, this happens, and recent Revolut scrutiny scares me)

In other words, I am looking for no-nonsense banking, and a debit card is just a small part of it.

This offering, unfortunately, seems to bring nothing new compared to Revolut.

<comment><USER3> As a modest counterpoint --

Things I do care about in a debit card:

* cash back on transactions I can't put on a CC -- i.e. rent * OFX/Quicken APIs I can use to import transactions * the ability to choose a PIN rather than memorize a randomly assigned one * the ability to send money via western union to family from my house * is accepted at all retailers / Paypal / misc * does not lose my money

Things I do not care about because I have other banking products:

* high APR on cash balances

Things that are dumb:

* emoji * large spend alerts / restrictions * card customization

<comment><USER4> I'm curious what landlords accept a debit card for rent payments. I've always been required to setup an ACH/automated transfer or give a physical check (note this is in California).

<comment><USER5> My landlord lets you pay with a debit card but they recently changed the convenience fee from $3 to $75 so you're now highly discouraged from it. It's porbably in general more common for large property management groups/complexes than smaller time landlords

<comment><USER6> "$3 to $75"

Can I just clarify that's not a typo? If you really don't want to offer the service that much, then don't? A $75 debit card (in)convenience fee just comes across as money grabbing, and harms their reputation.

<comment><USER5> Not a typo, it really increased from $3 to $75 (ownership of the building changed at the same time). I think it's purely a cash grab. But this city is a seller's market so they can probably get away with it. It's just a shame because the previous company that owned the building was so nice and lax about everything.

<comment><USER7> I have rentals and it's just a switch from eating the fee to passing it along to you. This is why most landlords still require paper checks, depositing them is free.

The % based fees don't make sense on large payments. Retailers pass it along too but it's baked in the price.

One tip I tell everyone, ask for a cash price when getting quotes. Contractors, etc especially. You might save 3% on Fees or 30% because he's not going to report it.

<comment><USER8> Debit card fees are typically like $0.20, for any size of payment though.

Only reason I can imagine they might be hesitant is because debit cards allow a customer to dispute a transaction, which can hold up capital while the dispute is resolved, and obviously the landlord might be forced to return a rent payment or two if the credit card company sides with the letter.

<comment><USER7> I think there is still a % component in the US anyway. It's smaller than credit, usually <1%. But brings up Another factor, in the US anyway, getting a merchant account to process debit transactions is not an straightforward thing, especially assuming It needs to be done online. Sure there's tons of options for credit square/PayPal/etc. But even a somewhat big apartment complex has only a couple 100 monthly transactions and it's just not worth the hassle for the landlord. No value add on our side equals no reason to change our ways. And yes, we change high fees to discourage behavior we dislike. I charge crazy high late fees because I don't want to be a debt collector. I actually have a thing I tell ever new tenant about how I will never bother them about payments being late because I'm not a debt collector. But they can expect a eviction notice on the N day late because that's what the state minimum requirement. My renters are never late.

</comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER9> I've seen debit card's with a points system at a credit union (just sharing so you can research) [https://www.redwoodcu.org/personal/redwood- rewards](https://www.redwoodcu.org/personal/redwood-rewards) I have no affiliation with them, had just been researching something similar a few months back.

I don't personally want to use a debit card for my everyday purchases, mostly for security reasons. I figure if I only use a credit card, then if the card gets compromised I can argue with my bank over the charges rather than asking them to put money back in my checking account while the fraud is investigated. Cashback on purchases is just icing on the cake.

<comment><USER10> I have similar concerns, although my wife and I have sworn off using credit cards due to candidly our lack of discipline paying the balance off in time. Do you think things like Apple Pay with the virtual cards provide that layer of security?

To any bank out there: I think if you offered a debit card that is backed by "virtual money" rather than the cardholders physical account, you would get my business in a heartbeat. The primary difference between the OP's answer is when your debit card is compromised, you are on the hook until the investigations are completed and still it is not a guarantee your funds are recovered.

<comment><AUTHOR> Also wanted to mentioned, we offer a virtual card for online purchases as a security pre-caution.

<comment><USER9> That's actually pretty nifty. I think you should add another section to your landing page about security that mentions chips, mobile wallets, and virtual cards for online payments. Those are all factors I'd look at when shopping for a new bank account.

</comment></comment></comment></comment><comment><USER11> Most credit cards have sign up bonuses worth a couple hundred dollars in points, that's definitely something to consider for your customer acquisition.

Not sure how you're going to compete in terms of CAC when banks are spending so much on this already.

Also, MR and UR points are transferrable to a ton of partners -- not all points are created equally, MR and UR points are some of the best at 2cpp.

Overall, since you're comparing yourself with the CSR, I would much rather get a CSR with 50K UR point bonus which is worth $750 in travel. I also get $300 in travel benefits, and I can cancel the card later to avoid the second AF from hitting. And finally, I earn points faster since it's 3x on travel and dining.

<comment><AUTHOR> We are exactly competition with cc's since we are a digital bank offering a debit card, and checking/savings accounts.

We are targeting a different type of user that: 1\. Do not qualify for a rewards card or have a dis-dain for credit (likely due to student loans & growing up during 08/09 crisis) 2\. Not interesting to banks (yet)

</comment></comment><comment><USER12> > The reason we don't see larger banks offering debit cards with rewards is > because of the "Durbin Act"; a federal mandate which slashed interchange > margins of banks with more than $10 billion in deposits. This was done in > order to protect consumers and merchants from increasing and predatory > prices that banks were trying to instill.

OOC, will this limit your growth in the long-term? What happens if you grow beyond $10B in deposits? Is the plan to partner with other small regional banks that have less than $10B in deposits, and does that circumvent the "Durbin Act"?

<comment><USER6> Agreed, also harms potential investment (limited upside).

What would be stopping you setting up a 'savings' bank. Set a higher interest rate on that, and make it trivial to swap the money between accounts?

</comment></comment><comment><USER13> I'm not sure I see the value proposition. Currently my bank (Alliant Credit Union) gives 2.08% on my savings and .648% on my checking. I'd say they're very reasonable with their fees considering I don't think I've ever gotten one.

For rewards I'd just use my credit card which is arguably better for daily transactions anyway. My bank even offers a credit card with 3% cash back in the first year and 2.5% after that.

So why would I use Point over already existing and arguably better solutions?

</comment><comment><USER14> Why should I prefer a debit card over a credit card, when fraud protections are so much better on a credit card?

<comment><USER15> Not OP but from their website it looks like they rely on Mastercard:

> Every dollar in your Point Bank Account is insured by the FDIC up to > $250,000, and unauthorized charges are covered by Mastercard Zero Liability > protection.

And Mastercard offers the same protection for both debit and credit card products[1].

[1][https://www.mastercard.us/en-us/about-mastercard/what-we- do/...](https://www.mastercard.us/en-us/about-mastercard/what-we-do/terms-of- use/zero-liability-terms-conditions.html)

<comment><USER16> Credit cards have specific legal protections and abilities (e.g. chargeback) that debit cards do not. MC's policy (thanks for linking to it!) offers none of those -- for CCs because there's no need, and for debit because the banks really really want to not provide them.

Ironically those protections were pushed for by the CC providers in the 1960s to encourage use of CCs. Now that CCs are ubiquitous, banks are pushing debit cards because they don't have those protections.

It's quite painful trying to get an ATM card from your bank that isn't also a debit card. Doable, but in my experience hard.

</comment></comment></comment><comment><USER17> My Chase debit card has had rewards for over a decade. How is this going to be better?

<comment><AUTHOR> We are initially focusing on life style oriented rewards similar to the Chase Sapphire Reserve credit card.

<comment><USER18> I don't see this as being competitive with the Chase Sapphire Reserve via points. The best use of points with this card is for travel. This can be done either using the points to book travel through their website for $0.015 per point or through transferring to their hotel and airline partners. Assuming someone also has a Chase Freedom United card they can get at least 1.5 points per dollar spent which is equivalent to at least $0.0225 in savings on travel. Combining this with a credit cards purchase protection and other benefits, why would someone choose your debit card over this?

Do you plan to add hotel and airline transfer partners to make your points more appealing?

Credit cards often have high sign up bonuses. The Sapphire Reserve launched at 100 000 points and later dropped to 50 000. If someone doesn't have one yet, why should they sign up for your debit card instead of the Chase card and putting all of their spending on it to earn the bonus?

<comment><AUTHOR> We are not trying to compete with an elite credit card.

Instead we are offering a product designed to combine some of the perks of a Chase Sapphire into a debit card which prevents you from overspending/going into debt.

Many people (especially younger millennials/gen-z) have thin credit files and a strong disdain for credit. We want to prevent folks from getting them selves into financial trouble without missing out on the good parts of having an elite rewards card.

</comment></comment></comment></comment><comment><USER19> Hey there!

What is the value of a point? You say '2x points,' but I can't find the value of a point anywhere on your website. Is it one cent = one point? How do we redeem points?

That aside, love the design and concept. :)

<comment><AUTHOR> Hi!

You're correct $0.01 = 1 point.

Initially points are redeemable for cash-back, eventually we will partner with different merchants where you will also be able to redeem points.

<comment><USER20> For what its worth, "2% Cash Back" sounds better to me than the ambiguous "2x Points".

</comment></comment></comment><comment><USER21> A few questions:

* What's the ATM network that you're using with no fees? Since I have good rewards credit cards that I can pay off every month, my debit card is essentially just for accessing cash and paying the very few bills I have that won't take a credit card, my debit card choice is entirely related to "no ATM fees, anywhere in the US."

* I'm a little confused about "All-in-one" including checking, savings, etc. Does that mean I'd get multiple accounts by default? Or does the debit card just pay HYS-competitive APY?

<comment><USER21> Very cool by the way. I've definitely looked for rewards debit cards in the past.

<comment><AUTHOR> Awesome to hear! We believe there is a fundamental shift towards debit especially as the new generation is burdened with student load debt and has a stronger disdain for credit cards due to growing up in the 08/09 financial crisis.

</comment></comment></comment><comment><USER22> Ive always wanted a better credit card to be honest. Something that had a insane amount of transfer partners, similar to how the starwood preferred guest card used to be. Something as simple as 1 point per dollar on everything and 2 points per dollar on dining/gas. The ability to also throw in the benefits that amex/chase cards offer would also be awesome (lounge access, return protection, roadside assistance, etc..) - I would switch to a card like that instantly. Im currently stuck putting all my spend on a American Airlines card, just because all the other options suck.

Now, with that said. I wouldn't use this product. Its not listed what the 'points' they give you do, so i can only imagine its nowhere near the value of being able to transfer them directly to airline or hotel partners. Im guessing its either a built in travel portal redemption they host or simply cashback. Either option is pretty garbage compared to other redemptions.

The interest is standard if you have a private bank, so its nice they give it to common folk, although i think many banks offer this now.

But most importantly, Using a debit card is risky. It lacks the chargeback and other protections a credit card has. (I could be wrong here, but I know it used to be this way a few years ago)

Anyways, dont take this as a negative guys. If anything, please continue improving your product and I will be a user. As it stands though, Its still lagging behind existing players.

</comment><comment><USER23> Minor suggestion: rework the "Compare Point to Other Banks" part of your homepage to better differentiate the two columns and explicitly identify which column is for which bank. While it's obviously implied that Point is the one on the left with the more impressive point (ugh) in the comparison, at first glance it's possible to miss that for a second until your brain catches up.

</comment><comment><USER24> As well as [https://www.pointbank.com/](https://www.pointbank.com/)

Rebrand in the making.

<comment><AUTHOR> Haha - we are not related!

<comment><USER24> 1\. You are trading very closely to their mark (financial services), leaving yourself open to these litigation issues from day one.

2\. If you succeed, you'll have to rebrand. You have a lousy and confusing name and domain (sorry for being brutally honest). We see this all the time. Rebrands are expensive as hell.

3\. If you fail, it will be largely due to naming.

Can't believe YC didn't tell you that ahead.

<comment><AUTHOR> Thanks for bringing this to our attention, it's definitely something we will keep in mind as we grow.

Appreciate the brutally honest feedback, it's usually the best kind :)

</comment></comment></comment></comment><comment><USER25> I dont personally care about points, but I do care about being able to make purchases without wondering who my bank is selling/trading the records to.

Points are manipulative anyway, they're designed to make people spend/do more than they ordinarily would. Eg, scene points, drug store points, credit card points, points in arcade games maybe even

</comment><comment> martin-adams I don't really have much to comment on the card itself. I'm from the UK and use a credit card for most spending due to the consumer protection it gives you.

One thing that I feel is extremely important, but not well executed in general is the budgeting. This does budgeting, but looking at it, I suspect it reports the categories of spending. The marketing site is somewhat vague at how that works. If that is correct, that's reporting not budgeting. Budgeting is allocating your spending to predict and plan for the future.

A couple of years ago I switch to YNAB and it's been a remarkable mindset change in how I manage money. I feel a lot of young people are missing out because they don't have the education or tools at the bank level to do it right. Most people I know of all ages do bank balance budgeting.

</comment><comment><USER26> This is pretty sweet! Looks like it checks all the boxes of what I currently have spread across multiple accounts and apps:

* Savings (want sitting cash to make market-competitive interest) * Checkings with no monthly fee * Budgeting analysis (if you can integrate with other Banks via Plaid or something that would kill 5 birds in one stone) * No international fees * Dining/travel points

## Questions:

* Do dining/travel 2x points apply internationally? And any chance this can become 3x? * 30k ATMs... compared to Schwab, who credit all ATM fees, how reasonable is Point to work overseas in the same manner?) * How fast (business days) do transfers take? * When is launch? * Mobile Apps --> do you support Android?

Great job, I think there's definitely something here.

</comment><comment><USER27> Is this a debit card that transacts as a credit card? ie you validate the balance on the spot, approve or reject the transaction immediately, and then run the transaction on the network as a credit card so you can charge credit card rates? (Enough for rewards)

<comment><AUTHOR> This is a pure debit card, it processes on the debit network.

<comment><USER27> So how are you able to collect enough transaction fees to cover the referenced rewards?

Does that debit card transaction fee limit only apply to banks with assets over $10B?

</comment></comment></comment><comment><USER28> Hello,

I signed up for your waiting list. I was redirected to a page with my current position in your queue. I have since lost that link and dont see a way to get back to it on your website. Can you provide a link on how to get back to this list?

Thank you, Joshua

</comment><comment><USER29> How do you plan on dealing with the nightmare of the other organization in the finance space that is named "Point" [http://point.com](http://point.com)?

</comment><comment><USER30> Your website mentions that a customer would receive 2x points on travel/dining which raises the questions of:

1\. how many points are received on non travel/dining purchases?

2\. what's the value of 1 point?

<comment><AUTHOR> 1\. No points for non travel/dining currently 2\. $0.01 = 1 point

<comment><USER31> FWIW, you lost me with "no points for non travel/dining currently". I get 2% on my credit card on all purchases, and I get 2.20% on my high-interest savings. I also have virtual card numbers, though admittedly through a terrible (Flash, so desktop-only) interface.

I can see how this card is great for people who haven't established good credit and need to use debit cards, but I'd think that even this audience would want to get credit cards so they can get improve their credit rating.

Innovation in the space is certainly welcome, so I'm absolutely rooting for you. For now though, it's from the sidelines.

</comment></comment></comment><comment><USER32> You mentioned the Durbin act which limit debit card fees. Since you're exempt from it, I assume you'll be jacking up fees for merchants in order to pay for your rewards program which is basically just a credit card.

This might not be a large enough of a pain point to be viable. Actually it might be detrimental to consumers who are living paycheck to paycheck. They rely on an incremental paycheck and short term credit fills the void.

<comment><AUTHOR> We don't have the power raise merchant fees that's dependent on the card networks (mc, visa, amex).

Our card is designed for people who don't/can't have an elite card but want to enjoy the benefits such as spending rewards, consumer protection, and travel perks.

</comment></comment><comment><USER33> "2x points" is advertised front and center, but since I couldn't find information on how they can be used or redeemed, I'm not sure if they are actually worth anything. For me, if you do not have, for example, airline transfer partners, I would not particularly value these points. FYI, optimizing for travel rewards is probably the #1 reason folks with a healthy disposable income use credit cards.

<comment><USER34> Noticed the same thing. I have a deep seated distrust for "point" cards. I guess I don't really fly much either, so airmiles are useless towards me. I just don't see the benefit of acquiring points in a corporation's economic fiefdom, where they control the value of both the currency and the products you purchase with them.

FWIW, I have a decent amount of disposable income and do use a credit card, but with cashback. I'm ~keeping pace with inflation and providing some sort of cushion between my chequing account and disreputable folk, so it's better than most other payment methods as far as I can tell.

</comment></comment><comment><USER35> Congrats on the launch. I would have thought that instead of trying to convert existing CC holders, you would have a better shot at converting cash/debit card holders who don't have great alternatives. Often these people will have low credit scores, keeping them from the very best CC opps, but by linking to their cash balance, you can give them rewards without having to handle credit risk.

</comment><comment><USER36> I read through all the marketing on the homepage and got to the end where it says it's currently invitation only and that one can sign up for the waitlist. Where exactly is the link to the waitlist? I tapped all over that box and didn't find any links. The contact link goes to Twitter, whereas your email address should be the main way to contact you (not everyone uses Twitter).

<comment><AUTHOR> Tap on "Reserve Your Account"

<comment><USER36> It doesn't work for me. There is nothing that accepts a tap or click on those words or in that entire box. I tried with iOS and Firefox on a computer.

</comment></comment></comment><comment><USER37> I couldn't find anything about the partner bank on your site. Most people probably won't care, but it matters to enough people to mention it.

<comment><USER38> All rights reserved Point Up Inc. Additional banking services supplied by Evolve Bank & Trust, Member FDIC. Point Card is accepted at all Mastercard locations.

</comment></comment><comment><USER39> Looking at the career section I noticed you're backend stack consists of:

Node.js, Express, GraphQL Yoga, Prisma, PostgreSQL, Docker, and Fargate in AWS.

I'm wondering why you chose JS for a financial services org instead of a language that offers more safety in the sense of types and memory control such as Rust or Go?

</comment><comment><USER15> Very cool! There's a lot about the banking industry that needs improvement so I'm always excited to see people trying something new. I'm curious if you have (or perhaps have applied for) one of the OCC's new nondepository "financial technology" charters?

<comment><AUTHOR> We have not (yet). Our plan initially is to focus on launching a live product in the market getting users/traction then exploring a fintech charter once we reach scale.

</comment></comment><comment><USER40> How does this compare to secured credit card offers?

Those are also backed by a linked bank account, and Discover offers good rewards:

[https://www.nerdwallet.com/best/credit- cards/secured](https://www.nerdwallet.com/best/credit-cards/secured)

</comment><comment><USER5> Will you be funding this with merchant fees? What about fraud protection, will it be as good as a credit card?

If the answers are "yes" and "no" it seems like there's almost no reason for me to pick your card over a credit card right? Unless I'm missing something big.

<comment><AUTHOR> Yes, the rewards will be.

For fraud protection there is 0 liability and we will credit you with the disputed amount instantly and there are several security features built into the card to protect you (on/off switch for ATM withdraws, daily spending limits, virtual cards, and instant push notification).

Point is a digital bank so we offer a checking account and high interest savings in addition to the card, so product/feature wise quite a bit different from a cc.

<comment><USER41> > instant push notification

Did you consult Apple on this? I was recently investigating Apple Developer Program T&C for APNS (Apple Push Notification Service) and they seem to expressly prohibit delivering financial transaction data over push:

> You understand and agree that in order to provide the APN and make Your Push > Notifications available on iOS Products, Apple may transmit Your Push > Notifications across various public networks, in various media. You > acknowledge and agree that the APN is not, and is not intended to be, a > guaranteed or secure delivery service, and You shall not use or rely upon it > as such. Further, as a condition to using the APN or delivering Local > Notifications, You agree not to transmit sensitive personal or confidential > information belonging to an individual (e.g., a social security number, > _financial account or transactional information_ , or any information where > the individual may have a reasonable expectation of secure transmission) as > part of any such Notification, and You agree to comply with any applicable > notice or consent requirements with respect to any collection, transmission, > maintenance, processing or use of an end-user's personal information.

<comment><USER42> Interesting. I've got several banking apps, each of which sends push notifications for charges. Either there's wiggle room on what's deemed truly "private", or everyone's openly violating this.

<comment><USER41> My thoughts exactly! It seems either all the banking apps have entered into special arrangements with Apple, or they are violating this provision out of ignorance or "me too" mentality.

</comment></comment></comment></comment></comment><comment><USER43> I bank with SoFi. 2.25% APY on a checking (like) account. $1.5M FDIC insured (not that I care/need it). Access to practically ALL ATMs. Beautiful app.

I use Uber Visa Credit Card, which is free, which auto pays itself from my SoFi, with helluva lot benefits: 4x dining, 3x travel.

Why should I use Point?

<comment><USER44> 1) SoFi, by itself, isn't offering you points 2) You're only getting points by using your Uber Visa Credit Card. That's defeating the purpose of this product which is getting away from CCs.

<comment><USER43> I'm really asking out of ignorance here: What's wrong with credit cards other than the fact that they don't bill my account immediately (which might actually be an advantage sometimes?)

</comment></comment></comment><comment><USER45> To reward your costumers for spending money is not exactly the same tactic of a traditional bank?

</comment><comment><USER2> > because we are partnered with a smaller regional bank

This here is the problem. This industry is heavily regulated and dominated by behemoths. You can't innovate when you are partnered with a whale. Sooner or later there will be an impedance mismatch.

</comment><comment><USER44> It's disheartening to join a waiting list then see that the top two spots are reserved by two of the founders. It makes you wonder how many other of their people are holding spots while we're sitting at 2,000th in line :(

</comment><comment><USER46> Is this for Americans only? There's no mention of availability on the website.

<comment><AUTHOR> Yes currently for US only.

<comment><USER39> Can you add that to the website? It's a glaring omission, as I was wondering the same thing.

</comment></comment></comment><comment><USER47> I think HN skews towards high income engineers who qualify for Chase Sapphires/Amex Platinum. Theres definitely a dearth of good rewards card for lower income people so I can see why this is a great idea.

</comment><comment><USER48> Why, when I can just use a credit card? What's nex, checks with rewards?

</comment><comment><USER49> Do merchants pay 3% on debit card transactions similiar to credit cards.

<comment><USER50> Yes - all payment processing networks impose a ~3% fee regardless of the credit/debit nature of the card.

<comment><USER42> Payment processors like Stripe may fix the rate at something profitable for ease of explanation, but the underlying interchange fees are _not_ the same.

They even vary by credit card type (rewards cards have a higher interchange rate than a non-rewards card), and by type of merchant. See the MasterCard rates at [https://www.mastercard.us/content/dam/mccom/en- us/documents/...](https://www.mastercard.us/content/dam/mccom/en- us/documents/merchant-interchange-rates.pdf), for example.

</comment></comment></comment><comment><USER51> Patrick - I'm in the payment services space. Do you have a phone number or email I can contact you at?

</comment><comment><USER52> Nice feature set. I'd also like to see an API/Direct OFX access.

</comment><comment><USER53> Loved the artwork so much, I impulse bought a print from Laura Berger!

</comment><comment><USER54> I thought everyone used a CC just to build credit. Guess I was wrong.

</comment><comment><USER55> Should have mentioned synapsefi in the website because it's big lie that they partner with this bank.

They really don't partner with bank. They use synapsefi

</comment><comment><USER56> whaah? We have had debit cards in Georgia (Country) with points for years now. Maybe first in the US - Yes.

</comment><comment><USER57> Instead of giving cashback/point, why don't lower the transaction fee instead ?

<comment><USER58> Because that doesn't benefit the cardholder. It only benefits the merchant. And, due to contractual restrictions, merchants cannot offer different prices based on payment methods.

<comment><USER57> Lower transaction fee will benefit the cardholder, it enable the merchant to lower the price of goods/service.

</comment></comment></comment><comment><USER24> Point.com is in the business of financial services. Sounds like you chose a terrible name.</comment>


Here's What Happens When You Wear a Low-Cut Top in Your Job Application Photo - <AUTHOR> https://www.yahoo.com/style/happens-wear-low-cut-top-150506053.html <comment><USER2> All right, I'm showing my age here, I guess, but when did job application photo become a thing?

<comment><USER3> > research from Paris-Sorbonne University

> application photograph (commonly used when applying for jobs in France)

Or did you mean you are also "old" and French?

</comment></comment><comment><USER4> They say "not cool", but proceed to do the same thing for their title and lead photo...</comment>