Live data from Hacker News

Goodbye, Clean Code

overreacted.io

571–580 of 599 posts

Re: Goodbye, Clean Code

#571

I’ve usually heard this phenomenon called “incidental duplication,” and it’s something I find myself teaching junior engineers about quite often. There are a lot of situations where 3-5 lines of many methods follow basically the same pattern, and it can be aggravating to look at. “Don’t repeat yourself!” Right? So you try to extract that boilerplate into a method, and it’s fine until the very next change. Then you ne…

I am working on a large project and I also realized this. I worked really hard to not repeat myself. I tried to reuse as much as possible as not to create extra code. Then, I quickly realized the things are NOT EXACTLY the same, and the methods to handle things were similar they were not the same. So, I had to refactor a lot of other helper methods.

I agree with the approach you are describing. It would be easier to refactor later, as one would probably have a better understanding of the application in the wild.

Re: Goodbye, Clean Code

#572

Earlier quoted context omitted.

The rule of 3 usually is in reference to small scoped abstractions, not whole modules or subsystems. We're talking about extracting a short function, not significant and potentially thorny chunks of code. I would say it’s for entire features sometimes. For instance, we are a B2B company. We have features on the roadmap or a feature might be suggested by a client. Either way, you hit the jackpot if you can get one cli…

That's been my experience doing embedded stuff. Customers will tell you they want a feature. You'll implement it then find out they don't need it enough to devote resources to utilize it on their end. So then it just lingers in the code base. And never gets real world testing. Lately I've been pulling unused features and consigning the code to the land of misfit toys. Just so I don't have to maintain them.

If that’s the case and they were willing to fully pay for the feature, at professional services + markup hours, it wasn’t a loss. In our case, we still got unofficially professional services and recurring subscription revenue and now we have a “referenceable client”.

If it’s behind a per client feature flag, it doesn’t cause any harm.

Re: Goodbye, Clean Code

#573
post #556

Earlier quoted context omitted.

So does that same idea apply to all of the many abstractions thst geeks do just to stay vendor or cloud agnostic just in case one day AWS/Azure go out of business?

Vendor agnostic code doesn't anticipate AWS going out of business, just them raising prices significantly. It can be smart to be able to switch in a reasonable amount of time so that you can evaluate the market every few years. This way spending extra time to be vendor agnostic can also pay off. But there's no technical reason for that, it's a cost issue.

It’s often noted that in almost 15 years of existence, AWS has never increased prices on any service.

What are the chances that AWS will increase prices enough to make all of the cost in developer time and complexity in “abstracting your code” and the cost in project management, development, regression tests, risks, etc make it worthwhile to migrate?

The cost of one fully allocated developer+ qa+ project manager + the time taken by your network team + your auditors, etc and you’re already at $1 million.

Do you also make sure that you can migrate from all of the other dozen or so dependencies that any large company has - O365? Exchange? Your HR/Payroll/Time tracking system (Workday)? Windows? Sql Server? SalesForce? Your enterprise project management system? Your travel reimbursement system (Concur), your messaging system? Your IDP (Active Directory/Okta)?

Re: Goodbye, Clean Code

#574

Earlier quoted context omitted.

> make it “generic enough to handle future use cases”. The answer to this is usually YAGNI. That is, don’t plan for a future you might never have. Code in a way that won’t back you into a corner, but you don’t know what the future’s cases might be (or if there even will be any) so you can’t possibly design in a generic way to handle them. Often you just end up with over-engineered generec-ness that doesn’t actually h…

The repetition is what is YAGNI! Repeating code 7 times in preparation for separate evolution of those 7 cases is YAGNI, unless the requirements are on the table now. Merging repeated code into one is something that is demonstrably needed now, not later.

It's not so much that you're preparing for 7 separate cases, as a thing that works in one place and almost, but not quite, fits in 6 others. You rarely exactly duplicate code, but often duplicate and modify.

By the time you hit 7, you do clearly Need It. But now you've got 7 cases to work from in writing the generalization. When the number is 2, it's often reasonable to say, "I don't know how these will evolve and I'll probably guess wrong".

Re: Goodbye, Clean Code

#575

Earlier quoted context omitted.

You call devs Junior until they have over 5 years experience? Wow, that’s harsh

> You call devs Junior until they have over 5 years experience? Wow, that’s harsh Less than 3-4 years is absolutely junior dev. Up until around 7 or 8 years is mid-level. Passing beyond that would be senior dev and the other titles then follow. With the obvious note that it's not strictly time bound - someone could easily get stuck at mid level for much longer if they aren't progressing. It's pretty hard to still be…

I agree.

I still very much consider myself junior but someone I know with less experience than me just recently got a job with "senior" in the title. I have seen senior job postings that say something like "3+ years of experience."

I absolutely do not consider myself senior and I don't think I will for at least seven more years.

Re: Goodbye, Clean Code

#576

Earlier quoted context omitted.

I generally find it pretty easy to reason about code structured like: switch(object) type1: (bunch of code) type2: (bunch of code) type3: (bunch of code) etc... Even if the function is long it's pretty easy to skip over the irrelevant parts. When you get in trouble is when you discover a bug (or have changed requirements) in something that gets duplicated several times and have to remember to hit all of them. The las…

> Even if the function is long it's pretty easy to skip over the irrelevant parts. > Overall the tradeoff is generally worth it though, because you only need to care about one case at a time. Which part is irrelevant? As a programmer, I don't generally know which value `object` has, so if I need to understand the whole statement, I need to look at every case, so I often need to check whether they are identical or sli…

It kind of depends what you're doing, but a lot of the time you are in a situation like "there's a bug when you do X", and when you find code like this you scroll through the options until you get to the one labeled as function X.

Inside of there you may run into stuff that was set up earlier in the function, but it's pretty easy to backtrack to the top of the switch statement to see what was done before then.

There's nothing quite like the joy of being asked to fix something and discovering that it's a big old top down project without excessive abstraction/compartmentalization. Just skim through the code in order till you get to the part that's misbehaving and start investigating. No need to jump around a dozen factory template engines or custom generic template wrappers to find the 3 lines of business logic that have an off-by-one error or something.

Re: Goodbye, Clean Code

#577

Earlier quoted context omitted.

> Java has a worst model of exception mixing weird typechecking rules + error handling not forcing to recover the exception. Unless you have a specific complaint about Java's model (which I'd love to read), I strongly suspect that your beef is with a few standard Java library functions misusing checked exceptions than a statement against exceptions in general. The combination of runtime and checked exceptions offers…

The big problem with Java's model is that exceptions aren't part of the type system: they're that whole separate thing that is applied to methods, but it's not a part of that method's type in any meaningful sense. This means that it's impossible to write a higher-order function along the lines of "map" or "filter" that would properly propagate exceptions, because there's no way to capture the throws-clause of the pre…

`> The big problem with Java's model is that exceptions aren't part of the type system

They are.

To the extent that the checked exceptions that a method can throw are part of the method signature (as all error cases should).

I have no idea what you mean by "exceptions aren't part of the type system".

Re: Goodbye, Clean Code

#578
post #300

Earlier quoted context omitted.

That's a test for your test, so why only run it once transiently instead of running every time? "Mutant" testing helps with this. It's basically fuzzing your test code to make sure that every line is meaningful.

I can see how that would be useful, but I also think it's a matter of priorities. I'm basically saying I rarely have bugs in my tests because I verify them first. In fact I can't think of a single bug in my tests over the last 4 years (or even 10 years), but I can think of dozens of bugs in my code. For example here are some pretty exhaustive tests I've written for shell, which have exposed dozens of bugs in bash and…

ITYM "I rarely have bugs in my tests that I'm aware of". The amount of tests I've seen that look like they are working properly, have been "verified" and are buggy is huge. Usually we find they were buggy because someone moves some other tests around or changes functionality that should have broken the tests, but didn't.

Please, don't ever assume that your tests are beyond reproach just because you verified them. Tests are software as well and are as prone to bugs as anything.

Re: Goodbye, Clean Code

#579

I’ve usually heard this phenomenon called “incidental duplication,” and it’s something I find myself teaching junior engineers about quite often. There are a lot of situations where 3-5 lines of many methods follow basically the same pattern, and it can be aggravating to look at. “Don’t repeat yourself!” Right? So you try to extract that boilerplate into a method, and it’s fine until the very next change. Then you ne…

My first job at a bigco had a very heavy read-the-code culture, and being able to read code and write readable code is one of the most valuable skills I learned there. The lack of this skill is one of the things I've found most frustrating about working with less talented or, now that I'm a bit later in my career, more junior engineers. There's a tendency to glom onto black-and-white, superficial rules without unders…

I'm about 70% down the page, and this is the best comment I've read so far. I think you should write a book, and/or a blog. I'd read it, anyway. :)

Re: Goodbye, Clean Code

#580

Earlier quoted context omitted.

This reminds me when a developer took over my codebase while I was on holiday. When I returned I had discovered that he converted all tab indents to spaces across the entire project. He completely destroyed my ability to perform diffs against earlier commits, because his preference was evidentially more important. Of course this was all justified with a link to Google’s coding style guide.

The commonality in both your and the parent's situation is that you reacted defensively. Your response was "You destroyed my tabs!" when a proper response would have been to try and understand your coworkers motivation. Perhaps he had some really good arguments for preferring spaces over tabs? Tabs can be problematic in heterogeneous environments where developers with different tab settings and different editors work…

> you reacted defensively. Your response was "You destroyed my tabs!"

> you shouldn't assume that.

He didn't say what his reaction was. You assumed it.

Am I missing something?

Post reply on HN