Conversation
Edited 5 months ago

THIS. So Much this.

This is what I am constantly trying to teach younger devs.

The best code is the most stupid-simple solution to the problem that runs in acceptable time.

The new intern fresh out of boot camp, with no understanding of the context should be able understand what it's doing.

22
2
0

@masukomi rubyists should also take care to not be overly clever with its metaprogramming capabilities 🫣

1
0
0

@masukomi Very much agree with this comic!

Can I ask a question about “complex abstractions”? I’m learning the basics of OOP right now which has included material on abstractions.

I’ve seen abstraction described as the reduction of complexity by creating simple interfaces. So is it even possible to have a “complex abstraction”? Or is it generally agreed that lots of abstractions taken together can become complex?

2
0
0

@masukomi I was just having a wee rant about exactly this! 🙏 🙌

1
0
0

@masukomi I wish I could click like 100 times :-).

I still with dread remember one of my first profesional coding projects, where a part got so complex, in large part by reusing the same thing for many different things, that it couldn't really be changed anymore without significant risk of breaking something else...

0
0
0

@masukomi I often use syntax tricks, abstractions, and high performance alternatives with the equivalent simple code and a reference Link in comments. I want the most elegant answer, but I want someone as ignorant as the business manager to be able to read it with a little help. (Perhaps even the sales guys? No on second thought, forget the sales guys!)

1
0
0

@masukomi
like this?

(k:=(lambda a:(v:=lambda c,ge,d:[(x-c(ge)/d(ge))**2 for x in ge],b:=sum,l:=len,
p:=input("[NdN?]: ").split("d"),f:=int(p[0]),h:=None,e:=__import__,srt:=sorted,
g:=srt([e('random',h,h,['randint'],0).randint(1,int(p[1])) for _ in range(f)]),
i:=(b(v(b,g,l))/l(g))**.5,s:=b(g[l(g)//2-1+f%2:l(g)//2+1])/(2-f%2),"x74657373",
m:=print(f'List={g}\nTot={b(g)}\nAvg={b(g)/l(g)}\nStd={i}\nMed={s}'),a(a))))(k)

it’s a dice roller neobot_cute

0
0
0

@masukomi @hrefna From an in-class activity I was just working up for the upcoming semester:

“In most circumstances, good code is not clever or complex; it is •obvious•.”

(Larger excerpt below for the curious. The activity involves reading different versions of English-language instructions for opening a door, ranging from absurd detail to “open the door.”)

1
0
0

@masukomi

I am convinced that Java stream operations exist for the sole purpose of generating incomprehensible stack traces.

0
0
0

@masukomi @marioguzman “clever” is a four-letter word when applied to code.

0
0
0

@masukomi Readable code should probably be near to spoken language ^^

These are some easy and very nice examples here:

https://python.land/readable-code

0
0
0

@masukomi I learned to put a lot of work into writing what I called "well, duh" code.

The hard part is figuring out how to frame the problem so that anybody reading the code thinks "well, duh" because it's so obviously the way to do it.

Admittedly, it's a little frustrating because the better you get at it, the more people start to wonder why you spend so much time staring into space instead of getting your job done. Doubly so when one of those people is your boss.

1
0
0

@masukomi Very much this.

IMO the best code is the code that I can glance at and, in as short of a time as possible, immediately (_and correctly_) know what it's doing.

Sometimes that's very difficult, but that's when the abstractions come in... to make whatever you _need_ to do as quick to (_correctly_) read as possible.

1
0
0

@masukomi 100% agreed. Can be easily demonstrated by letting someone explain code they haven't touched in 6 months.

0
0
0

@masukomi +100 - I tell my engineers to write code for other people, and to remember that "other people" includes you in 6 months.

Future You will not appreciate how clever you were when getting a service down page at 2am on a random Tuesday.

0
0
0

@masukomi I do my best to write my code in a way that someone years down the road won't be hunting me down to kill me. I'm not great, and I've already found out where I live...

0
0
0

@masukomi

Year X+1: What idiot wrote THIS? What were they trying to DO? Oh. This is my code.

0
0
0

@masukomi@connectified.com basically my ADHD has made me be the second after a few times x3

0
0
0

@masukomi this is going into my programming 101 lecture ❗

I cover this topic anyway and this is a very nice illustration for it 🥳

0
0
0

@count_bobby all programmers should be. I love that metaprogramming gave us something an clean feeling and usable as rails. But few people have the coding discipline required to do that and make it maintainable

0
0
0

@jimgar Someone else mentioned metaprogramming (monkeypatching & macros are examples of this). Significant metaprogramming is all about hiding complexity with a simple abstraction.

For example: in Ruby on Rails the models don't, by default, explicitly list their attributes. they are magically derived from the database they're connected to. Add a column to a table, restart your rails app, and the connected model suddenly has 2 more invisible methods for getting and setting that value

1/?

1
0
0

@masukomi
After 20+ years in the field, I TOTALLY second this.

0
0
0

@jimgar @masukomi If you're interested in a random person's opinion... I actually don't think that's a very good definition of abstraction. I'd say that any time you have "layers" of code, when a higher layer hides the details of a lower layer (i.e. using the higher layer means you don't have to think about the lower layer), that's an abstraction. Ideally the abstraction makes your code simpler to understand and modify, which means it's useful, but I think you could have an abstraction that makes things more complex, it'd just (probably) be a bad/useless abstraction.

Of course, sometimes an abstraction makes it possible to solve more complex problems that you couldn't handle without it, and then it might *seem* more complex, but I'd say that's different.

0
0
0

@wbpeckham i don’t want to be forced to go do research in order to determine if a coworker has made a bug or what the code even does.

I also don’t want to encounter code that’s going to make the imposter syndrome worse for the people i work with.

I don’t want to have to do research 1yr later when I’ve forgotten how the clever thing i did in my old code works

1
0
0

@inthehands @hrefna agreed, but i think there is an important aspect it’s missing. It should be obvious to juniors and new hires with no institutional knowledge.

To often we write code that is obvious to people who’ve been there for years but may as well be a paragraph of random jargon terms to an experienced new hire without the context

1
0
0

@adamsteer @masukomi

I like to think of code design as having loose and tight sensibilities.

Tight code is harder to maintain as you have to unbolt all the assumptions. But what it does, it does very well.

Loose code is easier to maintain, but is fatter, more repetitive and usually less designed overall.

Loose code makes great last mile engineering. But terrible APIs. Tighter code means more effort is put into code design and thinking about your "users" (other devs) needs.

0
0
0

@flagstone @masukomi
Hey, saving columns in Excel ain't nothing to scoff at!

0
0
0

@masukomi That's going to vary from language to language and framework to framework, etc., but yeah it's almost-always involving the simple stuff... like wrapping it in simple classes, or functions if there's no state to manage over time.

0
0
0

@jimgar that's not QUITE what you were asking though. Yes, anything can be made overly complex. Everything can be made harder than it needs to be. Everything can be written without considering context such that it looks simple in isolation, but is hard to use in a real world context.

I'm not sure what the person you're reading was thinking of other than that when they talked about "Complex abstractions".

a collection of oop models can definitely be too complex, but that's not really the same.

1
0
0

@masukomi Thus the comments, and my documentation. Even if they lose my documentation when they look at the source code there's the explanation. I figure part of my job is to make them not have to work hard at it.

0
0
0

@masukomi @hrefna
Yeah, “obvious to whom?” and “who is the reader?” are subtle and crucial questions for all writing, code included.

0
0
0
@KatS @masukomi I think the only way to demonstrate a skill for simplifying code is to start with someone else's complicated code, but even that may not be advisable if you're supposed to remain on good terms with the someone else
0
0
0

@masukomi Hey, thanks for the response. The material hasn’t said anything about complex abstractions - it’s in the first panel of the comic you shared :)

1
0
0

@jimgar oh. 🤦‍♀️

I assumed he was talking about things like getting funky with ternary operators instead of just using an if-else. I've seen examples far worse than both of these

foo = defined?(bar) ? some_function(bar) : "no bar"

or worse, combining ternary operations (this is valid ruby code off the top of my head)

foo = defined?(bar) ? bar.present? ? I18n.t(bar) : "bar is blank" : "undefined bar"

1
0
0

@jimgar ternary operators are a good example of an abstraction that can either be simple or complex

this is a simple abstraction of an if-else

foo= boolean_value ? "yes" : "no"

but as i showed in the last toot, a simple abstraction like that can be abused and turned into a complex one that's hard to read, or worse understand.

1
0
0

@jimgar thinking about it more, in real life it's almost always that a dev found some "clever" way to write something in one line instead of four. However that clever way is frequently something others don't know .

Here's a "clever" hack I use because it frequently saves me a lot of code, but i also know that only 1 of my coworkers has EVER had a clue what this was doing or why the * was there.

every time i use it i think VERY carefully if it's worth it.

0
0
0

I’ve gotten so tired of this take, which I find pretty anti-intellectual.

Yes, keep code as simple as possible, but the key part there is as possible. Legibility is only one axis to consider when writing code, and it’s a damned important one, but instead of having your entire codebase be understandable by a “new intern fresh out of boot camp”, I’d rather think of it as a codebase that’s understandable by leveling up that developer instead.

RE: https://connectified.com/@masukomi/113028352140788923

2
0
2

Because you know one thing that’s stupid simple? Doing concurrency control in code and not in the database.

Which is something that’s not necessarily always the wrong thing to do, even!

And I’ve encountered a fair number of new interns fresh out of boot camp who were unfamiliar with database constraints!

But how about doing the less understandable thing and teaching said engineer about database constraints instead of writing the more “understandable” code.

There are so many times I’ve had to make that tradeoff, and you know, sometimes you’re even net better off keeping the code understandable at the cost of correctness given a team’s context, and I’ve made that choice as well in the past. But it’s also not unreasonable to have code that is hard to understand because of essential complexity and that’s not approachable by the whole team either.

0
0
1

@alpha I'm reminded of the beginner's mess in Haskell that is "I need to know typeclasses to understand Monad, I need Monad to understand effects in this language including IO, I am eventually going to be introduced to algebraic effect handlers and actually have the right high-level concepts".

Concepts need to pay for themselves, but at the same time reasonably core engineering tools in the language - not to mention ones that are the right tool for a given problem domain - ought to do it pretty quickly.

0
0
1