Live data from Hacker News

Arguments against JSON-driven development

okigiveup.net

251–260 of 306 posts

Re: Arguments against JSON-driven development

#251
post #8

I disagree with the anemic object argument. If an object is just there to store data and no behaviour, then that's fine - don't add behaviour if it doesn't need it. A large portion of back-end services are CRUD and data wrangling operations anyway - as in, convert data format A to data format B (which I guess could be a constructor or factory method if you're comfortable with having the conversion logic in a data cla…

Especially true if your business objects are generated code, e.g., protocol buffers. Combining business logic with business objects is a mistake. That's a textbook example of tight coupling.

Where else are the business rules of an object supposed to go? Textbook? It's what you're supposed to do!

And if you say in a bloody "service", which just has the object passed as the first variable into every bloody method, I swear I'll come down there and strangle you with your own keyboard cord.

That's the actual textbook definition of tight coupling.

I'm working on a project which has 5 layers, business objects with no methods, a dto layer, a dal layer, a service layer and finally the website. All incredibly tightly coupled and utterly pointless.

It's an utter nightmare. Every time I touch the code half of it disappears, right now I've still deleted more lines than I've added while adding a ton of functionality.

That idea is so broken because it violates KISS, YAGNI and DRY all in one in a futile attempt to "decouple" things which are obviously coupled because the data is needed to perform the business rules.

There's a malaise in modern programming and it's the dogmatic pursuit of decoupling over simple and clear code.

Re: Arguments against JSON-driven development

#252
post #233

Earlier quoted context omitted.

Why do you not mind being poorly understood? The goal of effective communication is to have others understand you. Since you're not trying to communicate effectively, what exactly is it that you think you are doing?

> Why do you not mind being poorly understood? What I said I didn't mind is the “ire you are experiencing”. It somewhat saddens me that programmers, supposedly logical thinkers, can't see the distinction between a value and an object. > Since you're not trying to communicate effectively, what exactly is it that you think you are doing? I'm pointing to the distinction between values and objects pretty clearly: (0) Obj…

>It somewhat saddens me that programmers, supposedly logical thinkers, can't see the distinction between a value and an object.

We can see the distinction, we just don't use the same terminology you use. We use standard terminology by which what you call an object is a value. Your definition of the terms only shows up in an obscure part of FP, which is still a bit obscure in itself. Use alternate terminology, or explain yourself the first time you use it in a thread - otherwise, we'll all be confused.

I've tried to point this out to you at least three times, and I'm losing my patience.

This brings to mind another Munroe quote: "You're like the religious zealots who are burdened by their superiority with the sad duty of decrying the obvious moral decay of each new generation. And you're just as wrong."

Re: Arguments against JSON-driven development

#253

Earlier quoted context omitted.

> Why do you not mind being poorly understood? What I said I didn't mind is the “ire you are experiencing”. It somewhat saddens me that programmers, supposedly logical thinkers, can't see the distinction between a value and an object. > Since you're not trying to communicate effectively, what exactly is it that you think you are doing? I'm pointing to the distinction between values and objects pretty clearly: (0) Obj…

>It somewhat saddens me that programmers, supposedly logical thinkers, can't see the distinction between a value and an object. We can see the distinction, we just don't use the same terminology you use. We use standard terminology by which what you call an object is a value. Your definition of the terms only shows up in an obscure part of FP, which is still a bit obscure in itself. Use alternate terminology, or expl…

> We can see the distinction, we just don't use the same terminology you use.

No, most of the people I've talked to here clearly couldn't see the distinction between a value and its representation. (FWIW, I'm not fully convinced you can see it either.) They're not used to thinking about values without thinking about how they're represented. They're abstraction-challenged.

> We use standard terminology by which what you call an object is a value.

That's not consistent with some of the things other people have said here. But let's ignore that. What do you call what I call a value? Not that I'm a nominalist, but in practice, I've seen that people don't understand concepts they don't have a name for. (Though I probably have the causality backwards. It would be more accurate to say that, as soon as people understand a new concept, they rush to give it a new name.)

> Your definition of the terms only shows up in an obscure part of FP, which is still a bit obscure in itself.

It's not obscure. It's in the operational semantics of any call-by-value language, which for practical purposes means any language other than Haskell.

> I've tried to point this out to you at least three times, and I'm losing my patience.

Well, it's not like you have to deal with me if you don't want to. You do so out of your own volition. shrug

Re: Arguments against JSON-driven development

#254
I agree 100% with the article.

I've just written a script which makes every one of the mistakes listed in the article. I am consuming a JSON based API in a long ugly mash of code, exactly as described. It doesn't look pretty.

In my defence, I wrote the code as I was trying to understand the API. I had not read ahead and didn't really know which API's I would need or how fiddly it would be to bring it all together.

I am now exposed to pain if the API changes or if anything breaks. Time to go back and tidy up the code!

Re: Arguments against JSON-driven development

#255

At this point everyone should be using an evolvable (thrift, protocol buffers, avro, etc) schema format when they are storing or transmitting their data if they want to run an always on service - there is no downtime for migrations in the real world. Trying to do this ad-hoc with JSON is a lost cause and will eventually lead you to failure at runtime or worse, data loss situations.

JSON isn't un-evolvable. In fact, thrift can serialize to JSON.

What makes thrift evolvable in practice is that we don't remove fields and don't add mandatory fields. The same discipline can be applied to JSON definitions.

Well thrift also tags all fields with integers, so a consumer with an older schema can parse a record with a newer schema, skipping the new fields. Of course JSON trivially has this property.

Maybe the key here is "ad-hoc"; something like JSON-schema is needed.

Re: Arguments against JSON-driven development

#256
post #213

Earlier quoted context omitted.

You change your code. Loose coupling a nice goal to aim for, but at the end of the day, somewhere deep down inside the code, you have to tightly couple to actually get anything done. Where that transition occurs is entirely programmer's discretion.

But there's a difference between changing it once when you serialize/deserialize it, and changing it every time you try to access the key.

Writing the code with the assumption that a key will change is on the same level with premature optimization, in my opinion.

It might be reasonable to make the assumption for some keys. In these cases a function taking the data and key as arguments and returning the value is sufficient and appropriate.

Frankly, if the code base is so littered with references to that specific data and key combination it might actually indicate a poor design.

Re: Arguments against JSON-driven development

#257
post #51

I'm not entirely in agreement. Use of object-oriented programming paradigms here would merely distribute the logic that is necessary to achieve the desired mapping over multiple points in the code. The example function presented is only marginally too complicated. I'd split it in two: one to obtain the book list given the same arguments as the example function, and one taking the result as its only argument to build…

I'm also confused about this example. I've often seen similar code in C using structs. What's really missing for me is some context about why he wants these data structures and what he's going to do with them. Essentially he's doing a join on 2 tables and you are left with the thought, "Why do you need to do that join?"

I think what he's really trying to get at is that he dislikes the style of programming espoused by one of the child posters: Make everything a dict/hash and write filters than manipulate those dicts/hashes. I think the reason he dislikes it is for exactly the reason I'm confused about his example: you can lose track of why you need the types in the first place.

One thing you often see in Javascript (and I presume Python, although I don't have much experience in that ecosystem) is the idea that types don't matter. You have an object (essentially a hash) and you can transform it any way you want. If it is slightly more convenient to access your data in a different way, then transform, transform, transform.

Now all your functions have different signatures: "No, in this function we use the store inventory, which is exactly the same as a book list, but grouped by store". And then you have 25 different functions all doing slightly different versions of the same thing to keep track of all the weird mutations of types along the way.

Again, this isn't new stuff. We've been writing crappy code like this for decades. One of the nice things about languages like C++ is that it's such a PITA to define arbitrary data structures that you avoid doing it, but you still see variations of that theme even there.

As for OO or not OO, I think it's a red herring. If I have functions: make_foo(bar, baz), print_foo(foo), manipulate_foo(foo), or if I have a class called Foo with a constructor(bar, baz) and 2 methods called print() and manipulate(), it's exactly the same thing. Even if you write the equivalent code functionally, mostly all you are doing is moving the context (bar and baz) out of the heap and putting it on the stack (yeah... I know... lack of mutability is a pretty important bit too ;-) ).

This is almost as long as the original rant, but I'll jam one more thing in. Serialization, I think, has little to do with the problem except that people don't know how to separate their concerns at layer boundaries. The main bad idea that perpetuates is that I should have the same data structure in my database as is in my business logic as is in my UI views as is in my UI wigits as is in my communication protocols. Back in my day, we even thought that it was a good idea to serialize entire objects (with executable code!) from one end to the other, so I guess it's getting slightly better ;-)

To sum up: you can't ignore types even when it is easy to morph types in your language. At your layer boundaries you also need to transform your data from one set of types to the other set of types (and you should never expect that a 1:1 mapping is automatically going to be a good idea). Within your layers you should never mutate your types and you should write functions with clear signatures. OO helps you do this. Non-mutating state is also a really good idea and functional helps you do this.

Re: Arguments against JSON-driven development

#258

Earlier quoted context omitted.

>It somewhat saddens me that programmers, supposedly logical thinkers, can't see the distinction between a value and an object. We can see the distinction, we just don't use the same terminology you use. We use standard terminology by which what you call an object is a value. Your definition of the terms only shows up in an obscure part of FP, which is still a bit obscure in itself. Use alternate terminology, or expl…

> We can see the distinction, we just don't use the same terminology you use. No, most of the people I've talked to here clearly couldn't see the distinction between a value and its representation. (FWIW, I'm not fully convinced you can see it either.) They're not used to thinking about values without thinking about how they're represented. They're abstraction-challenged. > We use standard terminology by which what y…

There's a differance between being abstraction challenged and wishing to understand the abstraction.

We don't have a name for what you call values, as they're either irrelevant, or nonexistant in most contexts, and barely mentioned. However, we can't call them values, as that name is taken. Most CBV languages call them atoms, but that doesn't fit because they aren't necessarily atomic.

Let's try... Symbolic value? It seems to work: a given symbolic value represents all other equivalent symbolic values, and it's value that behaves like the symbol type in most languages. So that works unless it's already taken.

The point is, your definition of value needs a name that doesn't collide with the names of similar concepts and ideas. It doesn't really matter what it is. Unfortunately, this is one name clash that gensym can't handle for us. :-)

Re: Arguments against JSON-driven development

#259
post #7

Earlier quoted context omitted.

When using parsers like e.g. Jackson or Gson for Java, this process is completely transparent and does not require any active thought from the developer - well, maybe if there's very specific formats that don't map 1:1 with the class that should be instantiated or generated from the json object. It's a bit more tricky in JS, both client-side and node. You can't work with the json string there, but after that you work…

Automated serialization is the devil. Gson and Jackson require you to write EJB-style objects to get automatic serialization - default constructors, with getters and setters for each field - to achieve automatic serialization. The problem with this approach is that you've completely abdicated the power of the type system to ensure that your objects are valid. What happens if a field is missing from the JSON? Well, th…

if you're just using python for simple scripting and a random failure now and again isn't going to ruin your day, it's fine to just use json.loads, IMO. I've written quite a few scripts where the time it would take to do it 'right' wouldn't be worth the effort.

Re: Arguments against JSON-driven development

#260

Earlier quoted context omitted.

> We can see the distinction, we just don't use the same terminology you use. No, most of the people I've talked to here clearly couldn't see the distinction between a value and its representation. (FWIW, I'm not fully convinced you can see it either.) They're not used to thinking about values without thinking about how they're represented. They're abstraction-challenged. > We use standard terminology by which what y…

There's a differance between being abstraction challenged and wishing to understand the abstraction. We don't have a name for what you call values, as they're either irrelevant, or nonexistant in most contexts, and barely mentioned. However, we can't call them values, as that name is taken. Most CBV languages call them atoms, but that doesn't fit because they aren't necessarily atomic. Let's try... Symbolic value? It…

> We don't have a name for what you call values, as they're either irrelevant, or nonexistant in most contexts, and barely mentioned.

They do exist. Python has va... errr... the-thing-for-which-we-don't-yet-have-a-name: small enough numbers, special constants and object references. And they are relevant, because these are the things that you can bind to variables, pass to and return from functions, etc. If you think they are irrelevant, you don't understand them well.

> However, we can't call them values, as that name is taken.

I won't quibble about names.

> Most CBV languages call them atoms,

C is call-by-value. No atoms. Java is call-by-value. No atoms. ML is call-by-value language. No atoms. Maybe by “call-by-value”, you mean “inspired by Common Lisp”? That's not what call-by-value means, though.

> but that doesn't fit because they aren't necessarily atomic.

Right. In fact, the whole point is to use compound ones whenever we can!

> Let's try... Symbolic value? It seems to work: a given symbolic value represents all other equivalent symbolic values, and it's value that behaves like the symbol type in most languages. So that works unless it's already taken.

A symbol is supposed to represent something else, but a va... errr... the-thing-for-which-we-don't-yet-have-a-name doesn't represent anything else. If anything, what I call representations are the ones representing something else.

I propose “mathematical value”. Not everything you call a value can be plugged into an equation, but mathematical values by definition can.

Post reply on HN