Hacker News new | past | comments | ask | show | jobs | submit login

Elegant and clever code wont live through a maintenance cycle.

I'll take a software developer who writes and structures code so change requests and code are written in a way that the DSL is the same across the organization. This makes changes easy. Clever people should be writing libraries or doing research.

Don't kid yourself, you are either the guy who builds the building and its easy because its greenfield, or you are doing remodeling and the hard part is making the upgrade fit in the building and not look like shit.




Excellent comment. This is true, and I think golang embodies the idea (or attempts to). Enterprise wants consistency over anything else.

That said, there is a type of cleverness that can be brought to bear on Enterprise systems that, for example, take a simple, unidirectional data flow into account - something that is rather abstract, but which can and will thwart lots of complexity down the line.


Can you elaborate a bit on the golang part? As someone who dabbled with Go but never found it too alluring when comparing to other options (if I wanted ease-of-use I'd go with Python, if I wanted performance I'd go lower level - C++/Rust), I'm interested what you mean by it. Go did find a footing in the industry and a lot of cloud infrastructure relies on it, I do think it's the most interesting option out of compiled garbage-collecting languages.


Go finds a really good position in between. The language itself restricts your ability to get too crazy (with for example types).

I hate it, but I can totally see how it would work really well for keeping your architecture simple.


Go removes non-value added decisions as teams scale:

- formatting built in. There’s one way. No preferences needed

- language constructs are dead simple. There’s one way to use them, and they’re verbose. No cleverness encouraged

- patterns are straight forward Read the standard library code if stuck

Every Go project resembles every Go project. It’s great.


Plenty of languages have traveled that path, COBOL, RPG, xBase, Visual Basic, Delphi, 4GLs, Java, and now Go.

The problem is then you get some enterprise architects that go crazy with the design space.


The fix is to properly document your code. "Clever" code is an anti-pattern, but there's no need to make your code less elegant or less properly engineered than it otherwise could be. Hacked-together, low quality code is even less maintainable than "overly clever" code, so it's worth trying to avoid that.


Actually - I've found the "elegant properly engineered code" a total NIGHTMARE to deal with. Reflection, endless hierarchies, complexity on complexity.

The PHP script kid basically writes a linear program (tons of duplication) with no crazinesses. Yes, it's "low quality", but if you do a few function out refactorings you've got something very easy to work with.

I just wish there was a standard template - access check, runtime complexity at code comment at top of function (ie, O(1), O(n), O(n^2)) some reasonable comments, error handling, done. Throw in some unit tests if desired.


"Reflection, endless hierarchies, complexity on complexity" sounds like the exact opposite of "elegant properly engineered code"


You may not have worked with folks really into "properly engineered code". But it is amazing sometimes to see how they can twist language into pretzels by knowing every trick and pattern out there. And yes, somewhere in OOP land this is all proper engineering and the abstraction on abstraction on library on library is the key.

The worst is when they start talking about future this and that. Trouble!


That isn't properly engineered code.

And if you dig into all that code usually the designer didn't understand those tricks and patterns as well as they thought they did and were trying to teach themselves along the way.

You can often throw away 3/4 of the code, throw away 3/4 of the "requirements" which aren't being used and wind up with something that is actually simple and elegant and solves the problem, but doesn't attempt to construct anything as grandiose. Of course YAGNI is a whole lot easier in hindsight when you can really look over the course of years and see that nobody ever needed it so it never should have been built and throw it out.


Such features to throw away /s

(You must not actually remove any of them. Enterprise jokers will want all of it.)

- security (the most forgotten until it bites you)

- GUI flow complexity (client requirement you cannot touch)

- distributed state management with logical consistency guarantees (horizontal scaling)

- ability to quickly adapt for new features

- schema upgrade capability (see above)

- advanced database queries

- event reactivity and/or scheduling (logging, security, notifications)

None of the above is quite actually given to you on a silver platter by any one library really, it a combination thereof, and they're rather hard to grow bottom-up organically.


I think that the parent comment was expressing a disagreement with your definition of "properly engineered code". I agree with them -- simpler code is properly engineered, lots of complex magic is not.


I've definitely seen my share of impossibly convoluted code written in the name of "best practices" (often done because we need to "future proof" against some imagined future use case), but I've also seen my share of properly engineered code that was elegant, testable, composable and easy to work with (code that "cleaved the problem domain at the joints" if you will).

But what I think the author meant is that the incomprehensible abstraction soup is at least in part a result of the "enterprise development" method. If you are solving a particular problem for a particular application you tend to solve the problem in a straightforward way as possible (if you're any good at least). But if you an "enterprise architect" you are trying to create architectures that both solve no problem in particular and all problems at once. So you tend to get complex abstractions that are both complicated to work with and don't cleanly deal with any particular implementation.


Well of course, that’s why it was put in quotes. The problem is exactly that. Over and over again you’ll come across architectures that are massively over done but claim to be “elegant and properly engineered”.


yeah - the people actually keeping it simple (not designing for 100 future situations that will never actually show up) don't go on and on about elegrant properly engineered code. In general (exceptions exist of course) the entry level person writes much simpler code, focuses more on what needs to happen now.

etc


In my experience it's more likely the entry-level person who will write overly complicated code (or create such systems in general); they haven't yet learned how to identify potential approaches and to choose the most suitable one, and might not appreciate how many of their problems they don't actually need to solve at all.


I full heartely agree. Bonus point for globals you can set checked breakpoints on.

Linear long functions are victims of bullying. Sure, it is a balance act, but I take bad linear code over deeply nested code any day. When trying to figure out how code works I can't keep much depth in my head, unless it is some tree walk on a data tree.


Exactly this.

The person who knows all the "engineering" - you have this giant mutating pile of impossible to fellow (but maybe 5% faster) code.

The person who just codes enterprise style, long but done and easier to follow and edit.


I guess it depends on how you define "enterprise" but I always associated that word with unnecessarily bloated code. Or even worse, trying to reduce the amount of code by pushing more and more to ever more complicated declarative configuration files. That is mostly because when I hear "enterprise" I immediately think Java EE, which to me was the exact polar opposite of easy to edit and follow.


I think the hidden message in your comment is "duplication over abstraction" - and I agree! Often duplicating things is preferable to complicated abstractions.


Sandi Metz has a quote that was something like this "We don't tell me developers about avoiding duplication because it's so important, but because it's the only thing they understand".

Duplication is much better than the wrong abstraction


I find functions etc fine. But the problem is a lot of code let's you go absolutely crazy with complex design patterns - and folks who like to be "engineers" and "architects" go totally nuts with these. There was a fad I think around OOP (maybe with Java) which then bled into a lot of places. Yes, you can do crazy stuff, generics, meta programming, reflections etc.

But for example, if go just beefed up the standard library (especially around data structures - give us everything - and common functions there) I think they could have pushed a bit longer in terms of holding off on generics.


> The fix is to properly document your code.

I disagree that is the fix. I've seen horrible code that has extremely extensive documentation, and nice code with minimal documentation. I know which I would rather work with.

Documentation has its place, particularly for high level concepts and shared data and interfaces, and tricky, exceptional, or surprising things in the code itself. But it's a poor crutch for bad design or code.


This is 100% correct. There's no amount of writing about code that can make it better. In fact, if you can write well about what the code is doing, you can write the code well. It's a mystery to me that anyone expects people who can't write code that's clear and simple to then be able to write clear and simple prose explaining it. It's actually much easier to write code that only the computer (compiler or runtime) can understand, but it doesn't care if you name things meaningfully or if the structure reflects the problem domain.


I always wonder if people who talk like this have ever actually seen elegant and clever code.


Yeah, it's weird... like, if someone says that a math proof is "elegant and clever", I expect that to mean it is going to be a non-obvious way to make a complex problem that might have had a brute force solution easy to understand, where once you see it you go "oh wow, that's elegant and clever!"; but, somehow, there is an entire group of people (whom I refuse to work with, fwiw) who seem to believe that "elegant and clever" are bad things and wish for a world when everything is five full pages of algebra and number crunching... that you probably got wrong somewhere as there are now an infinite number of repetitive opportunities to make a mistake.


Everyone has seen elegant and clever code, but it's really not necessary when you're writing a CRUD API.


Then stop writing CRUD APIs; make the compiler do it instead. If you're doing rote, boring, assembly-line programming, then you're doing the compiler's job.


Imagine you’re working at a startup and trying to solve a tough real-world problem by creating software that involves writing some CRUD APIs. You bring on someone to the team who says, “we gotta stop writing these pointless CRUD APIs and write compilers instead.”

I’m not trying to be dismissive, but I think this actually well illustrates the central tension between engineers who are more interested in the business problem and ones who are more interested in solving technology problems. I know that when you get to a later stage as a company you need both kinds of engineers, but at an earlier stage company you have to ensure all of your engineers are of the former kind and not the latter kind or you will probably not succeed.


I work as a consultant, and we are also looking for talented people interested by solving business problems.

We actively avoid the technology-focused kind, because we know they will not be able to adapt to the work we do. To be honest, we write a ton of CRUD apps, but anyone who would come and say "let's write a compiler" is guaranteed to get funny looks. Even if you are extremely talented and can deliver to the same pace as we traditionally do, you will probably fail to consider one or two "little" things that would turn out to be fundamental requirements! Nobody is impressed by half-working cleverly written software.


It sounds like you're categorizing me as one of the people interested in solving technology problems more than business problems. In fact the opposite is true, to the extent that I've become a go-to person for questions on the domain I'm working in, even without any programming context around it (e.g. a senior technical review of an Excel document in the domain). I've become a recognized subject-matter expert in multiple business domains. If I'm not focused on solving the business problem, I don't know who is.

In fact it seems like it's quite the opposite: people who think in terms of loops, conditionals, and objects seem to be happy writing repetitive CRUD APIs all day. People who think in terms of business logic want to write business logic. You don't need to write your own compiler (it's weird that this became the thing I supposedly suggested), but you do need to develop good abstractions and data structures that fit your domain to get your code looking more and more like just a spec in the domain language.

The "don't reinvent the wheel" people who want their programmers to just bang out repetitive API code all day aren't any closer to the business logic than I am. They just don't understand what makes good software, and they don't realize that the wheels that are available to them out of the box actually suck for their task and always need some modification.


For me elegant and clever means that 1) my code won't get in your way and 2) can be thrown away easily.

In return I ask a bit more time so I won't self-couple my code with introspection magic or make it undebuggable with weird dynamic design patterns nor will I make wormholes to so that A can communicate with B.

Deal?


deal. code should be written to be easily replaceable, not extendable

to me, more often than not, it means simple


In my enterprise experience the remodeler usually just ends up bolting more shit onto the existing heap of shit.

Dev time ends up taking longer and longer, wasting more and more money.

Its funny you mention greenfield being easy in the same sentence - because IMO starting over is often the better option than the shit bolting but no one wants to go down that route because they need it next week. A whole bunch of small shit bolting projects every week instead of sitting down and cleverly engineering better broader solutions.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: