Live data from Hacker News

Write code. Not too much. Mostly functions.

brandons.me

261–270 of 362 posts

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

#261
post #159

Earlier quoted context omitted.

>I don't always need to have n+1 layers in my architecture where all the layers just call the next layer anyway. This is by far the most common thing I’ve seen consistently in especially difficult to maintain codebases. Anecdotal for sure, but number 2 on that list is way behind. Extra abstractions for a future that has yet to happen and abstractions because the IDE makes it easy to click through the layers is the nu…

One of the best products I've had to maintain recently was a cgi app with very few abstractions, many of the pages in the app didn't even have functions, just construct sql, read it and spit out html. If someone had a problem all the code was right there in a single file and the error could be found patched and deployed in minutes. Over the years there were a couple of attempts at replacing this legacy system with a…

Counterpoint - code like that is OK if the project is small and tidy, but over a certain size, changes become horrible refactoring efforts and adding multiple developers to the mix compounds the problem. The 'enterprisey' rework that you describe sounds badly architected, rather than an example of why architecture is bad. Good architecture is hard to do but I don't agree that means we're better off not bothering.

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

#262

Earlier quoted context omitted.

"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.

"to identify which components of what you are building _must_ be perfect"

Well, but by the words of your former CEO (and my opinion) those parts would then have infinite costs, too... if they really need to be perfect. I mean, it is awesome, when you do a big feature change and it all just runs smooth without problems, because your design was well thought out, but you cannot think of every future change to come - and when you still try, chances are you get stuck and waste your time and risk the flow of the whole project. I rather tend to think about the current needs first and the immediate future second, but everything after that, I spend not much thought anymore.

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

#263

This nugget stood out for me: "In my experience most codebases have a pure functional subset, and I believe writing that subset in a pure-functional style is nearly always a win for the long-term health of the project." This is probably often true. In high level applications, the idea of classing or abstracting out your i/o from the core functionality is appealing from a security and reasoning perspective, but not su…

IMO it's useful for code which is heavy on logic/decision-making. Code which is mainly about hooking systems together and managing state benefits from it much less.

I also find that people who are used to a certain kind of project (e.g. heavily logical) and spend years on it have this tendency to assume all code is the same way.

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

#264

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…

This is a good question, and I haven’t yet seen anyone reply with (I think) the real answer: it’s not the rule of 3 so much as “not 2”.

When you start adding a new feature, and notice it’s very similar to some existing code, the temptation is to reuse and generalize that existing code then and there -- to abstract from two use cases.

The rule of 3 just says, no, hold off from generalizing immediately from just two examples. Wait until you hit one more, then generalize.

“Once is happenstance, twice is coincidence; three times is enemy action” (Ian Fleming IIRC)

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

#266

I like the sentiment of this article. It's a great analogy. Might be a little off topic, but it reminds me how I am happy that the Go programming language and its philosophies gained popularity even though I don't use the language regularly. Watching Go talks made me appreciate simplicity and clarity. It made me accept that I don't always need to use every design pattern in the book. It made me think about the reader…

The bold utilitarian approach of Go might face some valid criticisms from seasoned programmers, I myself had to empty my cup(mostly Java) to get onboard Go and I'm glad that I did. After a spine surgery my programming time got severely limited and so I decided to code my future projects with utility focused languages. I had used Python in the past, but the performance tuning once the application scales is counterprod…

How do you feel about coding without generics now, and what do you think about Go's ambition to add them?

I'm coming from a C# mindset and thinking of learning Go, but I'm so used to generics...

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

#267

Earlier quoted context omitted.

It's pretty simple. x = 1 addSomething(y) = y + x The above is not a combinator. addSomething relies on the line x = 1 and is forever tied to it. You cannot reuse addSoemthing without moving x = 1 with it. Therefore addSomething is not modular. This is the root of organizational technical debt. When logic depends on external factors it cannot be reorganized or moved. This is also a big argument against OOP because OO…

hah i was taught that style is "pointless"... it comes from topology, no?

Yeah that's a fun name for it. It is often a useful style:

    map (not . elem [2,3]) [1,2,3,4] ===> [True,False,False,True]
or

    grep foo bar.txt | wc -l
Also chaining in OOP is a bit "pointless", in that it doesn't mention the "points":

    foo.bar().baz()
But, like most things, it's best _in moderation_.

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

#268
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…

Perhaps we just imagine different things, but I like when code is a list of human-readable calls to functions. The implementation of these functions isn't so important to understanding the code you're reading.

This works really well as long as you use pure functions, because their impact on behaviour is clearly restricted.

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

#269
post #49

Earlier quoted context omitted.

My beef with mutable data is that it's often very hard to see when it's supposed to be modified and by what. I don't get upset by a local var i in a while loop, although I often don't see the point. The problem is the dark mutable data. All those objects being passed around, are they just being read?, are they being modified by this method call? So if mutable data is used responsibly, it's not a problem. But there's…

You can rely on a type system that help you to use mutable data responsibly, à la Rust.

I'm not familiar with the type system of Rust but it seems like a really nice language.

Ofc a type system that helps you deal with mutable data responsibly goes a looong way to alleviate the problem but it's not a guarantee. And often times such a type system comes with weird and unexpected quirks. Here are some examples from C#:

For example "readonly" is not immutable, it's a compile time guarantee that a value can only be assigned in the constructor of a type and to that instance of the type only.

This means that for type Foo with readonly int bar, you can have a constructor Foo(...) : this(...) and the value of bar is mutable in the context of those constructors. For most intents and purposes however, the "readonly" only field however acts immutable enough to give a reasonable degree of immutability.

The you have something like private setter functions. They go a long way to guarantee encapsulation of state. But there's no compile time guarantee that an instance of Bar int baz { get; private set; } won't mutate the baz value of any other Bar instance. In-fact, it's a common misconception that private modifiers make something private to the instance, whereas it's only a compile time guarantee that it's not visible to any other type.

Furthermore, private modifiers don't actually prevent anything from actually utilizing it in runtime. You can simply use reflection or other techniques and do what you will.

Then you can do other weaker forms of type-checking "immutability", for example only exposing getter functions in a IFooReader interface.

These things all help alleviate "dark mutability" to different degrees but the underlying values are still mutable. I guess the point I'm trying to make is, yes, it massively helps to have a type system that guarantees encapsulation and immutability to different degrees. The caveat is that we are still at the mercy of that type system and the way it enforces immutability is often non-obvious and less immutable than one might expect.

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

#270

I like the sentiment of this article. It's a great analogy. Might be a little off topic, but it reminds me how I am happy that the Go programming language and its philosophies gained popularity even though I don't use the language regularly. Watching Go talks made me appreciate simplicity and clarity. It made me accept that I don't always need to use every design pattern in the book. It made me think about the reader…

Golang and simplicity in the same sentence does not quite reflects my daily experience.

Want a Set? Golang does not have one, create a map[type]boolean instead.

Want an Enum? Golang does not have one, create a bunch of constants yourself that are not tied together by a type, or create your own type that won't quite make what an Enum is.

If simplicity means feeling like you are programming in the 80's, that is what Golang meant for me with simplicity.

Not having basic stuff such as Set and having to workaround with a map of booleans is not simplicity, as you will have to make it turning the code into a more complex blob to represent the same kind of data structure.

I could go on and on with the list of things that lack instead of things that are simple.

Post reply on HN