Live data from Hacker News

Write code. Not too much. Mostly functions.

brandons.me

141–150 of 362 posts

Re: Write code. Not too much. Mostly functions.

#141

So, I have a question. I have a kind of serial number, and different systems expect slightly different formats. One system likes dashes, one doesn't, one system likes an extra two digits, while another system likes an extra four numbers. Should I write around n(n-1)/2 pure function converters between n systems? Or one class with n methods? (If you're curious, I'm talking about oil well API numbers. It's not rocket sc…

Why n(n-1) pure functions? It makes no sense that you only need n methods in a class and suddenly n(n-1) pure functions. You will always need n(n-1) functions if you want to specify ALL the conversion logic. Think about it. If you're not writing it in the method, then that logic must be written down somewhere.

I think I get where you're coming from though. The class hides a type representation that is used as the "internal" representation of the serial number so you only need to write 2n functions. N function to convert to the special serial types, and N functions/logic to convert the special serial types to the internal serial type. The latter N functions are placed in the constructor not as functions but as a series of procedures to deduce the type of the parameter and do the conversion internally. (The effect of this is identical to overloading the constructor).

Let's say A represents that internal serial type, with all other letters in the alphabet representing the serial types of your oil well. You're essentially doing the same as writing:

  AtoB :: B -> A
  BtoA :: A -> B
  
  CtoA :: C -> A
  AtoC :: A -> C
If the goal was to convert B to C with classes you do this:

  Serial(B).CtoA()
with functions you do this:

  AtoC(BtoA(A))
Your BtoA logic is simply hidden in the constructor of Serial. But basically the exact amount of written logic is occurring here.

I think your question was a trap. One class with n methods is obviously better then n(n-1)/2. I think you were just unable to see that it's basically all functions and expressions in the end. When you use classes you are simply tying these functions to structure and internal variables making them less modular, but the amount of logic is exactly the same.

But overall, if you want to know which methodology is logically better and more resistant to technical debt then I will tell you.

The functional approach is better.

Because the functional approach modularized BtoA. BtoA can be reused in other contexts in the functional approach but in the Object Oriented approach the logic of BtoA is tied together with CtoA, DtoA, EtoA and all of that in the constructor. Likely if you needed that logic as a one off... say to print the serials in internal receipts... you would likely be copying and pasting that logic from the constructor and duplicating it in another class when you follow the object oriented approach.

This is the main reason why the author of the post promotes pure functions. Greater modularity and greater resistance to technical debt.

Re: Write code. Not too much. Mostly functions.

#142

I'll take it one step further. Don't just write pure functions. Write point free combinators. Have you guys ever wondered why no matter how much care or planning you use to organize your code when you begin a project, some time down the line you will always encounter a situation where the organizational scheme you chose is less than ideal or even flat out wrong? It's a sort of inevitable technical debt that occurs. T…

Can you describe that in simpler terms? I read the wiki and the Python example seems to suggest writing functions that take a single argument.

Yes, and you can later do fun things with these functions, it seems: https://markshroyer.com/docs/pointfree/latest/overview.html

Re: Write code. Not too much. Mostly functions.

#143

Earlier quoted context omitted.

Hard same. The best organizational level technique I've found so far is to add the rule of three to code review checklists. An abstraction requires at least three users. Not three callsites, but three distinct clients with different requirements of the abstraction. Obviously it's not a hard rule, and we allow someone to give a reason why they think that it's still a good idea, but forcing a conversation starting with…

Why 3? Rule of three sounds catchy but logically it's just a arbitrary number. Similar to SOLID and KISS, why pick some arbitrary (and also obvious) qualitative features and put it into an acronym and declare it to be core design principles? Did the core design principles just Happen to spell out Solid and Kiss? Did it happen to be Three? Either way, in my opinion, designing an abstraction for 3 clients is actually q…

While I usually like the zero-one-infinity rule as a go to when there aren't any other constraints, when trying to build an abstraction it can be fairly tricky to suss out the parts that actually are share vs what is actually different. Two unique and independent users could share a lot of process &c randomly, 3 is a little less likely.

Re: Write code. Not too much. Mostly functions.

#144

Maybe an apt analogy for the "not food" described here could be YAML and other config. I have seen way too much logic buried in strings in miscellaneous config files. It's so annoying to work with.

That was my initial impression of systemd.

Systemd has these stupid config files. And by stupid, I mean that literally. They replaced init files (with arguably too much logic) with these simplistic config files that have no logic available.

What ends up happening is you replace init files with nothing, and you have to push out any logic to an intermediate script or binary which just adds indirection.

Re: Write code. Not too much. Mostly functions.

#145

Earlier quoted context omitted.

Abstraction here likely means more than a function - maybe something like an interface base class?

That’s not what I took from it, but even if that’s what was meant, I think I’d have the same reaction. In terms of abstraction implementations, a class is just a different expression of the same idea of encapsulation.

Given the context of the posts that it was replying to, my impression was that they meant the "rule of three" applied to an entire abstraction layer.

Re: Write code. Not too much. Mostly functions.

#146

Earlier quoted context omitted.

It's easy to say ugh, but we juniors are more than willing to learn "the right way". This is the hardest part for me. I get anxiety about it and it slows me down. How do I apply this to taking over someone else's 4 year old Magento project? We're out here doing our best, and sometimes our learning environments are in that context.

"the right way" I would say, don't stress about it too much. There is no perfect way. Everyone makes misstakes. And about when to make abstractions and when not, is mostly about experience. There are modules worth optimizing and abstracting. And others are not. You definitely will make wrong decisions about it and later found out, this optimisation was a waste of time, or that quick and dirty approach really cost you…

> wasted too much time thinking about the right approach in a neverending, neverprogressing loop to achieve perfection

A CEO from my past often muttered that "perfect software comes at infinite cost". It's key, imo, to identify which components of what you are building _must_ be perfect. The rest can have warts.

Re: Write code. Not too much. Mostly functions.

#147
post #44

Earlier quoted context omitted.

As I get older my code gets a little more verbose and a little less idiomatic to the language I am writing. I’ve been writing code, starting with C, since 95. Mostly Python these days, but I try to make it clear and easy read. Mostly for myself. Future me is always happy when I take the time to comment my overarching goals for a piece of code and make it clean and well composed with enough, but not too many, function…

> well composed with enough, but too many, functions. In my experience, code with too many functions is more difficult to grok than spaghetti code. It's like trying to read a book with each sentence reference a different page. So, I try to code like I would write, in digestible chunks. > As I get older my code gets a little more verbose I've seen too many of my previous projects die right when I moved on. Now I tend…

> In my experience, code with too many functions is more difficult to grok than spaghetti code. It's like trying to read a book with each sentence reference a different page. So, I try to code like I would write, in digestible chunks.

This is so true. The worst code that I've dealt with is the code that requires jumping to a ton of different files to figure out what is going on. It's usually easier to decompose a pile of spaghetti code than to figure out how to unwrap code that has been overly abstracted.

Re: Write code. Not too much. Mostly functions.

#148
post #58
post #46

Earlier quoted context omitted.

GOPATH is hated because it's poorly thought-out. It's poorly thought-out because Go is designed by Google, who uses Bazel for dependency management. GOPATH is only there because you can't expect everyone to adopt Bazel in order to adopt Go, so some half-assed solution gets designed to get the language out the door. In simpler terms, the people who designed the language don't use GOPATH at all. That's why it's terribl…

I don't think GOPATH is poorly thought out at all. Dependency-environment-locating is a PITA. Off the top of my head, I can't think of a single package management system that doesn't use universal installs, FOO_PATH or "giant local dump per project". Universal: - apt, yum, brew Team PATH: - GOPATH - CMAKE_PREFIX_PATH - PYTHONPATH (which Conda, virtualenv, etc modify) - CARGO_HOME Team redundant local blob: - Node - p…

Nix isn’t any of these? It installs each replicable version of a package once, but it’s not visible outside of the project that uses it.

Re: Write code. Not too much. Mostly functions.

#149
post #137

I'll take it one step further. Don't just write pure functions. Write point free combinators. Have you guys ever wondered why no matter how much care or planning you use to organize your code when you begin a project, some time down the line you will always encounter a situation where the organizational scheme you chose is less than ideal or even flat out wrong? It's a sort of inevitable technical debt that occurs. T…

IME, the limitations of this recommendation appear when one needs to combine multiple functions taking multiple arguments, some being fixe and some other not. Although they are mostly syntactic, they hamper the readability of the resulting code.

I agree with you. Readability is definitely worse when using this method. It doesn't mean it can't be circumvented with good naming.

Overall though this method basically solves the problem with technical debt I described above.

The root of all dependencies come from free variables. So if you get rid of free variables and turn your functions into combinators, then all your logic is modular.

If you get rid of all variables then all your code has to be combinators.

Perhaps the point free style goes to far in terms of readability. Maybe just switching to combinators is a good middle ground. In layman's terms for the readers who don't understand this means don't even use pure functions in classes. Just use functions.

Re: Write code. Not too much. Mostly functions.

#150

Earlier quoted context omitted.

Hard same. The best organizational level technique I've found so far is to add the rule of three to code review checklists. An abstraction requires at least three users. Not three callsites, but three distinct clients with different requirements of the abstraction. Obviously it's not a hard rule, and we allow someone to give a reason why they think that it's still a good idea, but forcing a conversation starting with…

Why 3? Rule of three sounds catchy but logically it's just a arbitrary number. Similar to SOLID and KISS, why pick some arbitrary (and also obvious) qualitative features and put it into an acronym and declare it to be core design principles? Did the core design principles just Happen to spell out Solid and Kiss? Did it happen to be Three? Either way, in my opinion, designing an abstraction for 3 clients is actually q…

I think setting hard limits on design is a good thing. Creativity needs limits. If your limits can imply something about your desired design goals then that’s a good synergy. It also forces the engineers to think more about design rather than fall back on their goto pattern that may or may not fit the problem. Especially junior and mid level engineers might not have good heuristics on is their design any good or is it just following whatever cargo cult they were brought up in.

Like one engineer on my team implemented this crazy overkill logger and I asked a few questions why do it like this and the answer was that they had implemented it in another language at another company. After that I told them to not have more abstraction layers than concrete implementations when adding a new feature.

Post reply on HN