In the decades Java sources have been available, any of the kazillion junior programmers could debug-step into java.* and see exactly what's happening -- progressive disclosure at its finest for building expertise.
Most other languages have a hard boundary, so the roots of language are a matter of conceptual documentation and experience. Java also offers that fly-over knowledge, but when problems arise, programmers love knowing exactly and seeing directly.
Personally, in a pinch I prefer the actual to the elegant.
While I think there's a lot to love about Java, the standard library itself is not an especially great role model. Most of it was written a long time ago and has a fairly antiquated style - lots of mutable state, nullability, and checked exceptions. Not that the library isn't an incredible asset - it's luxuriously rich compared to working in Node.js - but if it were written from scratch today, I suspect it would look fairly different. Eg, the collection classes would use Optional and have separate read/write interfaces.
For an example of "modern Java" I would point at something like this (which I wrote, sorry about the hubris):
As much of a fan as I am of Java, I have to agree. There are some real bombshells in the library that can either make your coding life or debugging a prod service miserable (sometimes both). Other additions are great, but have hurt readability a bit (i.e. Java lambdas).
Checked exceptions get a bad rep, but I've frequently found taking advantage of their hierarchical nature can be beneficial to at least making them less bad to catch. When I work with languages that have no exception support at all, I sometimes even miss them.
As much as "not" a big fan of java, I need to give credit where it is due.. as my (almost) first language almost 25 years ago I learnt heaps by going through the source code. Sure there were bad and (what are now) outdated conventions etc. But as a junior eng learning how layouts worked, how data structures were implemented, how network code was written and tons more, the Java src folder was a huge treasure mine. Did I mention swing?
From your repo: Respectfully, I disagree that checked exceptions are a misfeature. Java’s implementation definitely leaves a lot to be desired (inheritance doesn’t make sense for them), but otherwise checked exceptions are a better form of Result types.
Unchecked exceptions are the better version of Result type.
The problem with checked exceptions is that methods throwing them force its callers to react to the even if they are irrelevant to them. In 99% of cases I don't have any JSON specific error handling, yet Jackson forces me to do a try-catch-rethrow ceremony in thpse 99% to declare I don't want to do anything specific.
That’s the not too comfortable part. But with a tiny bit of syntax sugar (say, a ! or ? that expands to a mini-try-catch block) it would be more than fine.
After a decade of programming 50+ hours a week in many languages (typescript, javascript, python, scala, java, lua, bash, c++, etc), I have come to the conclusion that Java is simply the best. The tooling, libraries, stability, verbose rigidity. It forces a style of programming that simply scales to more engineers better
As an end user though, I honestly can’t think of any Java software I actually enjoy using. Minecraft? That’s literally the only thing that comes to mind.
This was true for me as well until I used DBeaver (a universal database browser tool) I only realized it was java after I tried connecting to a really old server that needed me to change my ssl settings in the JRE. The user interface feels fairly snappy. DBeaver is a really fantastic tool and I don't see myself changing any time soon. It even supports making its own SSH tunnels to your database server using your local ssh agent.
I can attest that AWT and Swing were hot garbage 20 years ago, though. The cross-platform aspect worked great, but the algorithms weren't worth making cross-platform to begin with. It was basically a giant GUI ecosystem written by people with no understanding of how to implement graphics efficiently. My favorite was how they bragged about their "lightweight" visual components that don't require OS-level window objects. Except, OS window objects are part of an algorithm that tracks exposure regions and repaints it efficiently without needing to redraw the whole screen. Swing took the approach of repainting the entire application window in a back-buffer on every visual change and then copying that up to the entire application window area, even for things as small as tooltip pop-ups or menus.
I haven't checked which GUI framework DBeaver is using. I suppose it's possible that it is Swing and my workstation is just so fast these days that the inefficiency doesn't matter.
I think you just don’t realize when a given software is Java. I personally really like intellij, one might say it is “bloated” (though I hate that word), but that’s only because of indexing everything, not due to java itself.
On the server front many cloud infrastructures themselves, apple servers, pretty much every top 500 company has some form of business critical infrastructure chugging along on top of the JVM happily.
Oh no, I realize what software I use is Java. Swing feels bad to use. On my workstation at least, JetBrains IDEs are slow, I haven’t used it in a long time, but Eclipse was slow, NetBeans was slow, there’s an enterprisey Java web start application I need to use at work and that’s slow. Like I said, Minecraft is the only piece of software written in Java that I enjoyed using.
I think java is geared towards server applications because the JRE is so finicky about memory and other machine level details you can only control on your own services
Most major web services have java microservices that take on the performance critical and logic intensive parts of the business
Take some time to learn the navigation and refactoring abilities of the JetBrains family. It is IMHO unmatched by most. Using almost any other IDE feels like a downgrade, especially on large codebases with complex dependencies. Beyond Java, they have excellent support for Python, C#, Go, Javascript, and more. The engine builds a deep understanding of your code, which can make ctrl-space to suggest a method on an object feel delightful (and a Godsend on big Java names).
I also strongly prefer the keyboard shortcut set JetBrains uses. Having to reach all the way up to my function keys for combo operations makes me sad; even when I use other IDEs I love using an Intellij keybinding when available to quickly jump in and be efficient.
But to your point, I also tend to use it on higher end workstations (i.e. minimum of 16GB RAM, local repo pulls on fast SSDs, tons of logical cores, etc.).
Used JetBrains for more than 10 years, but got tired of it lagging all the time and using so much memory (even on M1 Pro with 32GB RAM, even on small projects). So I switched to VSCode for everything except Java. And I’m not a person who is easily annoyed I would say.
They seem to have fixed a lot of the weird lags recently. Right click context menu used to be slow, and the python debugger had performance issues for sure up to a year or so ago. Both way better now
They limit the usable memory way too low by default — if you have RAM increase it to at least 2GB, but 4 may be even better and it will be snappy as hell.
Java doesn’t enforce any particular style. I’ve seen extremely procedural code that is full of statics where it’s obvious the authors were attempting to write C in Java. I’ve seen all manner of attempts at OOP where classes were meticulously restricted to nouns and the opposite where every class was a Service/Verb. Of late I’ve seen Java server side code that’s drank the reactive kool aid and done it’s level best to recreate NodeJS in Java.
Now, your assertion about scaling to more engineers may be true but I’d argue tooling is the main reason for this because Java certainly doesn’t enforce any particular style of programming.
I'm using C# and Java professionally. I've been using for a long time while I'm newish on C#. Also I'm on a older version of .net vs. a modern Java. Honestly to me the language doesn't feel that great. It always feels sluggish, to work with, like I'm fighting against the language. And then there is the ecosystem, Spring Boot is just such a breeze to get a web app running with all the integrations you could ever want being just there. Add in Lombok and Apache commons and it's a real pleasure to develop in Java for me.
The ecosystem is nowhere near as mature though. I don’t work with either anymore but back in 2017 I made the switch from C# to Java and it felt like a breath of fresh air when it came to the maturity and capability of JVM tooling compared to what’s available for .NET.
Try JetBrains Rider, and be sure you are using a recent flavor of dotnet. When I migrated past 4.x to 6 of the .Net ecosystem, it dramatically improved my ability to work and deploy in C# with their rather delightful build system.
For example, in the Monogame game library, you can build a self contained binary for Windows, Linux or MacOSX nearly effortlessly with just a single command line.
The ecosystem is certainly more mature than many smaller languages, but it is still in a different league than Java’s. Most of it is not too great copies of the corresponding Java library, often being made by Microsoft only, with plenty of paid options while in the java world all of it is open-source and free, while offering a much wider selection.
Also, you will find a java library for that random new tech you want to use, while it is likely missing for .NET.
In javaland, the actual ideal is somewhere in the feature set supported by Groovy. CompileStatic groovy is probably the best, you get a lot of good features for no performance hit.
Java was the language I used in university. While it may be well structured, I hated it as a junior level dev. There’s just so many unnecessary classes and abstractions to accomplish basic stuff.
It makes sense in large applications with experienced developers, but it sucks to learn.
It was very sparse with any syntactic sugar or ways to shorten common operations. Now it's much better, especially if you eschew the 00s style of programming - with obligatory getters and AbstractSingletonProxyFactoryBeans.
My experience with languages is that people want more exotic languages as they gain experience, than they grow away from them and go back to pragmatic ones. I think Java strikes a great balance here, and while I also had a phase where I thought how much better Scala is for example, I can appreciate java much more nowadays and will default to it for most projects.
Go and it’s standard library. ‘Elegant’ is pretty subjective, but it’s a treasure trove of learning how things work under the hood. I’ve learned loads about networking, compression, encryption and more by browsing through it, because the code is super easy to read and understand.
What makes it easy to read and understand though? I am seriously having a hard time figuring this out. People tout Go for this all the time, but I don't know of a single codebase in it that I think fits that description. When I look through them they look convoluted and just sort of messed up. Things like awkward error handling, dealing with null, capitalization for public/private, magic functions, and imports, and much, much more all add up and make me abhor the language. I don't think it's good or easy to use at all, but people rave about it.
Speaking for myself, the language itself is simple. There aren't a lot of features, which means you do have to write more and it's more verbose, but learning the entirety of the language's features is very easy to do.
Even with the relative magic of things like init functions that execute on import, there's so much less magic that you have to consider.
IMO it's the easiest to jump into for this reason. Yes, the code itself might be excessive, but reading Go is as simple as can be.
I'll echo this. When I'm looking at a Go codebase that somebody else wrote, it's a minimal effort to understand what it does. Rarely, if ever, do I scratch my head at a particularly clever type derivation or obscure language feature; macros are pretty much non-existent; even user-defined types are easily reduced by the IDE and language server. Patterns are standardized and yes, it's verbose, but predictably so. If something calls for containerization, it's dead simple. Go is a language for getting things done straightforwardly.
I know it's not everybody's cup of tea, and that's fine. There's room for different languages in the world. But I'm knocking out useful utilities that make a difference for my team and business in days or hours, and supremely uninterested in code golf, so I don't personally agree with the criticisms.
Its touted as being so easy that a junior dev can pick it up easily; it's targeted towards average developers. Fine, this is a virtue; when Java said the same thing, it's a horrifying blight.
The other is that people seem to mistake motion for action. "The code flies from my fingers" is one way I've heard it said. And, sure, you have the same error catching boilerplate (which again, in go is a virtue but other languages seems to be considered a sin) 1000x, as if the clicky-clicky of the keyboard is some measure of productivity.
It's got a big "blub paradox" thing going, to my eyes. I don't find it elegant at all, or maybe I mean not very expressive.
Taken ad absurdum, I have a language that only adds 1 to a variable. I can understand that language in milliseconds. But I can't do much with it. Maybe go hits a good balance, I dunno, but I found it quite tedious.
It’s the complete lack of magic. What you see in front of you is pretty much exactly what happens. You don’t have to keep a cathedral of language semantic subtleties in your head when reading someone else’s code.
That’s because JavaScript is an awful language and I just don’t understand why people keep insisting on using it for everything. It even infected infra as code.
That’s because it is easy to use. Maybe you use too much python or Java but go was designed to specifically allow people to memorize the entire syntax, truly.
Want to make a function or variable or field public? Just capitalize it. That’s it.
Error handling? Check if the error isn’t nil and handle it, otherwise move on. No need for silly things like try except.
And there are no magic functions because everything is explicit.
Try except isn't silly it shortens the code a lot. An exception can simply break out of a function, checking for error requires an explicit check at every line of the function and an added return statement to get out of the function.
At my employer we use a subset of C++ and we use Go. We have a process by which when you write code others have to review it and you need to have a review by someone who is an "expert" [0] in the language [1]. You become an "expert" by being ordained by a shadowy committee who reviews code you submit to the code repository. They look for knowledge of the core language, how this language is used within the company, the external and internal libraries, performance, testing, etc. There are many factors and if you demonstrate all of them you get marked as being this type of "expert."
Before I joined this company I had written code which was launched into production in the following languages: Java, PHP, C, C++, assembly (arm + x86), Python, JavaScript (browser + node), and a few more. I would consider myself about average in all of these. I did not write any golang.
After I joined my current job I obtained this "expert" bit for both C++ and Go. It took ~1.5 years to get the C++. It took ~3-5 months for Go.
You can actually see the first golang code I wrote (this was at home when I was experimenting with the language before convincing some team members we should rewrite some of our infra in go): https://github.com/gravypod/gitfs
It has all sorts of mistakes but I didn't read any guides. I just used https://cs.opensource.google to search for examples of things that I thought I would need to do (ex: "how do I do a switch statement").
For C++ I had worked on ~2 projects that used it. My first few PRs were very rough and I had a lot of performance issues that crept into my code. If I didn't already have a lot of C experience I would have also had a bunch of pointer/lifetime stuff the reviewers would have found (I know this from reviewing new team members first lines of C or C++).
I know that to some C++ represents a literal worst case but most people coming from C++ to Go will think it's amazing because it removes all of the common footguns.
> Things like awkward error handling
Yes, it is very clunky and annoying but it's very simple. It's just a normal if statement and doesn't use any special language rules. I think this would still be better if there was dedicated syntax for it (something like throw/try/catch which works the same way but gives it a different syntax) but honestly I don't think it's as bad as it's made out to be. It's basically a "less bad" errno and that worked go-... dece-... ehm fine for many years.
> dealing with null
I've never really had to think about this too much. There are some times it is important but I rarely return nullable things without errors and it hasn't bitten me yet. My code is not provably correct but for the things I'm working on I don't need that guarantee. If I did I'd probably switch to Rust or something with better type safety.
> capitalization for public/private
Yea, this sucks but it doesn't really get in my way much. I don't like it but it isn't actively hurting my usage.
> magic functions
Like `String()`? I don't know if that's the worst think in the world. Python, C++, and Java have things like this.
> and imports
It's not been too bad for me. What I think is unfortunate is that the package of something is unconnected to where it is in most go usages which is annoying but it makes things more terse. This does actually hamper my productivity.
> I don't think it's good or easy to use at all, but people rave about it.
It's pretty easy to use because all of the libraries I've seen share common interfaces for behavior. This makes things feel a lot more cohesive. fuse-go and billy was very easy to use in gitfs because of this.
[0] - This is not an expert as in "knows everything" but more like "has been seen to consistently write efficient, simple to understand, idiomatic code." It basically means that when someone else from this subset of SWEs reviews your code they often do not have many comments. Again, I want to stress, this is not expert as in "knows everything" just as in "good enough".
Well, c++ is literally the most complex language, famously not even Stroustrup would say he knows the whole, so comparing go to that hardly makes it look good.
No, because the different trade-offs they make all have costs and benefits. For example, C’s precise memory management can give better performance compared to PHP, but also requires more expensive programmers to work with it. If all you’re doing is a simple CRUD system, C’s power would be counter-productive, so PHP is a “better” language in that context.
So a “good” language depends on what you’re trying to do with it.
I remember with smug satisfaction a time that I was able to settle a pedantic argument from a so called "security expert" by pasting the code from the library function he was questioning.
Very satisfying to be able to say "nope, it's fine, here's the source".
I find the Golang standard library code annoying to read and understand because of their use of single letter variables or very short abbreviations. I know some people like this but I don’t.
The single letter variable is only supposed to be used within a relatively short function or code block. They should be relatively obvious; I personally find this to work well, but I can understand where sometimes it wouldn't be clear what the author was referring to.
RT-11 on the PDP-11 (all in PDP-11 assembler). Back in the early 80's you could rebuild it in several different ways, depending on whether you wanted it "single job" (as it was back then) or not.
As an example, here's the PDP-11 assembler to convert a binary number to decimal ASCII (no idea who wrote it, but they certainly made every word count):-
CNV10: MOV R0,-(SP) ;Subroutine to convert Binary # in R0
1$: CLR R0 ;to Decimal ASCII by repetitive
INC R0 ;subtraction. The remainder for each
2$: SUB #10.,@SP ;radix is made into ASCII and pushed
BGE 1$ ;on the stack, then the routine calls
ADD #72,@SP ;itself. The code at 2$ pops the ASCII
DEC R0 ;digits off the stack and into the out-
BEQ 2$ ;put buffer, eventually returning to
CALL CNV10 ;the calling program. This is a VERY
MOVB (SP)+,(R1)+ ;useful routine, is short and is
RETURN ;memory efficient.
> R - sf package is a clean example of functional OOP
Funny because I detest it because of how difficult it makes it to dig into and customise spatial data and visualisations at a low level like I am used to with the spatial packages it sort of supercedes
Jet.com has a lot of good ones yeah. One I was looking through the other day is a GitHub repo under /ScottArbeit/Grace and it’s an interesting take on version control. It was a pretty cool repo to look through. To make it easier though, remember that F# source code files are all “in order” so you read them from top down, which Github doesn’t currently have functionality for.
For folks coming here later, you can figure out the order that you should view them in by reading into the `.fsproj` file, which will lay out compile units in order.
Shewchuk’s Triangle code for Delaunay mesh generation is some of the most elegant C-code I’ve ever seen [1]. It even won the SIAM Wilkinson Prize for numerical software at the time it was written.
It’s written in a literate style, and builds up from the most fundamental arithmetic operations and data structures, all the way to one of the most efficient mesh generators of its kind.
He has a few other codebases written in a similar style [2, 3]. It’s very different from what you see in the wild, but it’s been great for understanding what’s happening under the hood for complex algorithms like mesh generation.
Working with Perl, two things spoiled me for other languages: JSON and DBI/DBD.
In Perl, everything serializes to JSON without fuss. It can be "lossy"; objects without an explicit JSON serialization method and coderefs can't be deserialized, but serializations at least have placeholders for them.
Compare to Python's json module, which doesn't try very hard to serialize things and throws exceptions every time it runs across something new. It's very frustrating to use.
Perl's DBI provides a universal API for all databases, with implementation-specific details in an underlying DBD module (which both provides glue between the DBI abstraction and programmer access to features specific to different database systems).
Compare to Python, where you need to import a different module and use a different API for every different kind of database. As I increasingly use Python for a living, I frequently wish they'd follow Perl's example with this.
Funny enough, but I've come across some really nice Perl code in the wild at work. I was used to the vendor providing some 40 class Java monstrosity to do something that should take like a page of code, so I was pleasantly pleased to find a contractor who provides an extremely well commented page of code to do something simple, yet critical to operations. The way Perl calls the OS to do something and glue everything together was pretty elegant.
You might really like Ruby! It's part descended from Perl and maintains a lot of the nice things about perl such as json, and the amazing string functions.
I tried very hard to like Ruby. "On paper" it looks great, but I had a lot of trouble getting used to the syntax.
I ended up going deep on the D programming language for my "new language". As a statically typed language it's not as expressive as the Python/Ruby/Perl contingent, but it's a lot more expressive than most static languages, and its C-like syntax "clicked" with me in a way Ruby never did.
It also can approach C-like run-time performance and memory footprint at times, which I appreciate. As much as I like developing in Python and Perl, I frequently wish they had better run-time performance and a smaller memory footprint. D gives me that, at the cost of a little expressiveness.
Omg the python stdlib json / simplejson both refuse to support custom serializers for keys only, as an explicit design decision. It is justified as "JSON keys must be strings", but JSON values can only be string/float/book/null so it seems a bit arbitrary. Leads to annoying gymnastics if you want to enforce "strong typing" of keys with Enum/pydantic/etc.
> In Perl, everything serializes to JSON without fuss. It can be "lossy"; objects without an explicit JSON serialization method and coderefs can't be deserialized, but serializations at least have placeholders for them.
> Compare to Python's json module, which doesn't try very hard to serialize things and throws exceptions every time it runs across something new. It's very frustrating to use.
Sounds kinda backwards to me. I thought the fact that throwing exceptions (or "making a fuss," if you will) is better than silently producing incorrect (or "kinda lossy," if you will) results wasn't controversial anymore in 2023.
I really like Pandoc codebase [0]. It is a document converter written in Haskell.
Reading it’s source code a decade ago was a turning point for me. Prior to that, I always felt an insurmountable gap between my toy codebases and real projects. All those open source software written in C++ etc. looked so unapproachable that I felt like I could not write production ready software.
Pandoc however, was written in a language I didn’t know and did something very complicated very thoroughly, yet remained accessible. It was very nicely laid out and I could easily follow how it constructs it’s internal representation of documents and converts between them. I think this made me catch the functional programming bug for the next decade that let me build way bigger things than I had any right to, without getting crushed underneath all the complexity.
Putting together something in Java or even contributing to OOP Python codebases was still like an exercise in frustration, no matter how much better I thought I’m getting at programming I would feel stupid trying to wrap my head around those abstractions and hierarchies. Somehow FP just clicked for me and made me see how I could start from a simple library call and little by little build the complete program.
Today I am comfortable with all kinds of paradigms and levels of abstraction, but I definitely owe a lot to Pandoc for showing me I was smart enough to understand and modify real world software I did not build myself.
At the beginning of the year I was rewriting a SPA and looking for ideas on how to structure a web app. One project I looked at was Github Desktop and I think it has very clean code for an app.
I use it daily and it works great. It doesn't do all that much, but what it does do saves me a bunch of time. I reach for the git CLI when something goes wrong, but that's not often.
It completely ignores the simple UI paradigm of tabs or a sidebar. You should be able to move between repos without blowing away whatever you're in the middle of. I'm forced to be in one at all times, and I can't manage multiple repos at once via a simple sidebar. It's like it takes all of the inherent arcane complexity of Git and creates a UI that is so barebones it almost mocks you for deigning to ask for a GUI.
I've really enjoyed reading (and playing with) kons-9's codebase in Common Lisp. It lets you do exploratory 3D modeling via the program's GUI or the repl. The source is very neatly structured and readable. I don't see many CL projects that do 3D rendering, so it's nice to see!
For C, I've really enjoyed reading the Ruby source code. There are good and bad spots, but overall especially if you know Ruby the language, the source is both entertaining and enlightening.
Probably helpful to understand the API first before understanding the implementation. There is a well known guide here: http://silverhammermba.github.io/emberb/
I’m surprised that nobody has posted about Elixir yet. I nominate the excellently written Phoenix library. Not only is the code well organized and easy to find, the documentation is expansive and right next to the code.
I was going to say this too. C is more my "consistently appreciated" language than ever my favorite of the moment, but the Redis codebase is a fantastic example of it that's very easy to digest.
I don't know if elegant is the word, but I often refer to the Hashicorp repos for Go, and specifically admire Mitchell's own. Very clean, well written code most of the time.
An old one, but the FTGL library (renders truetype fonts in old-school OpenGL in half a dozen different ways: texture-per-letter, texture-per-word, 2D polygons, 3D polygons, etc) is the best example of C++ inheritance I've ever run across. The code formatting isn't my favorite, and comments are sparse, but the hierarchy of objects subclassed for all the different rendering modes is just about perfect. https://sourceforge.net/p/ftgl/code/HEAD/tree/trunk/
The first version of KDB the timeseries database was written by arthur in C to bootstrap the K interpreter that was used to write KDB. It was 26 files, named a.c to z.c, none larger than a single page of C written with notepad.exe.
fs2 (reactive streaming, https://github.com/typelevel/fs2) written in Scala. It shows how nicely things can compose in a typesafe way if the language supports it.
And then, the opposite is Monix (https://monix.io/) also written in Scala. It's also about reactive streaming and the API is great, but the internal code is ugly because it sacrifices readability/composability for performance.
I'm currently using Laravel at work. It's very opinionated, and some folks say it uses anti-patterns with regards to its use of facades. That being said my last job was C#/.Net and I am so much more productive with Laravel. It really allows you to develop quickly and I haven't yet bitten by any of the "anti-patterns". If you give it a shot I'd recommend just using Laravel Sail as, if you already have docker installed, you can have a full dev environment setup in less than 10 minutes.
It is and it isn't. It does opinionated ways of doing things. But IMO what makes it so great is just how easy it is to opt out of the opinions you don't like. Facades are an excellent example of this: don't want to use them? Well, you don't have to (and IMO a really big app that may be a good choice - in a small app it likely won't matter and you might as well use them).
Although at a high level many of things things are subjective, this take is almost entirely wrong in every dimension.
Anti-patterns are things like using a wrong data structure, using the wrong levels of abstractions, tightly coupling components so they are not composable, leaky interfaces, god objects doing too much
The strict definitions of many of these can be subjective at the edges, but they all objectively exist and cause fragility, instability, inflexibility and maintenance problems in the systems built from them.
Clean code is code that’s easy to read, has the right level of abstractions, uses the right data structures and has the minimal possible anti-patterns in them (ideally zero!) above.
Calling these things bogus is unfair, I grant they can be subjective in some places but they are prevalent in poorly designed systems especially by junior engineers.
Anti patterns are real. Clean code is real. If you cannot see that, I would suggest reading a lot more codebases from open source projects (pick medium and large codebases, not trivial programs) and after 10 or so you will see obvious structural and quality differences, as well as hundreds of anti patterns and examples of clean code.
I'll agree with everything here except the clean code. Clean code is about optimizing human perception and there can't be a standard for that because humans think in a wide variety of ways and it's further impacted by the level of understanding the human already has on the subject matter the code is dealing with. One person's "clean code" can be another person's nightmare.
I'll back this up with the example of Magento 1. It's a PHP e-commerce platform that has (at first glance) some of the cleanest code you'll ever see in PHP. It looked like the entire development team had come from a Java background. Every component was neatly divided into a PHP object with documented private and public methods. There was a clean MVC separation, with lots of shared behavior abstracted into "Helpers", and a Theme system handling the rendering of the front-end. I have no doubt that the authors of Magento prided themselves on how clean their code was. For them, having spent full-time careers structuring all the many features of their platform into these files, it probably did feel like a clean organization. And when I initially reviewed the code to evaluate using Magento, I also thought it was clean and was part of my choice to use it.
The problem was that when you take something as complex as a full-featured e-commerce system and modularize it so thoroughly, you end up with a literal 7000 classes, and it becomes impossible to figure out the sequence of execution of a single page request through that massive tangle. Is it "clean code" if I have to add debugging print statements to 57 source files to figure out the path of execution that renders a single page?
If I had to choose a circle of hell where I would edit Cyrus IMAP (the worst C code ever) for the rest of eternity, or edit Magento for the rest of eternity, I think I would actually choose Cyrus.
> Anti-patterns are things like using a wrong data structure
What is a "wrong data structure"? Is it wrong to do linear scans when hash access would be sufficient?
> ... using the wrong levels of abstractions
When is the abstraction level wrong? I can name you at least 10 projects that avoid so called anti-patterns by introducing unecessary abstractions. Is something really an anti-pattern if it's "solution" massively reduces your development velocity but now everything is nicely composable?
In my opinion, anti-patterns are either obvious (constantly using different names for the same thing) or totally subjective to the context (when to repeat yourself).
But maybe I'm not able to put myself into the shoes of novices and a lot of things seem obvious to me. Granted.
I've seen people use multiple named arrays, search for something in the first array, then use its index to find matching data in the other arrays, instead of a dictionary of string:tuple.
Another example is languages with arrays and vectors, usually one or the other is preferred. In Go you can use arrays but you're supposed to use slices whenever possible, while the opposite would be appropriate in, say, C.
Not the OP, but clean code misses the point. Its is very subjective and depends on one person's previous experience and patterns they've been exposed to.
"Reasonably readable" is what I strive for nowadays, and a key aspect is that I no longer think there is an objective measure for it. It depends on the team/company you're in, and its important to keep in mind that the goal is to effectively communicate the program to them.
Armin Ronacher is definitely one of the engineers you should follow on GitHub, especially if you're writing Python or Rust. That guy is a genius at what he does.
Oddly, even though he wrote one of the two most popular frameworks for Python, Wikipedia still claims his entry doesn't meet notability requirements.
I try not to toot my own horn, but I wrote this little quadtree library that tickles that elegance part of my brain. I try very hard to write elegant code. I have other Clojure repos, but they suck. :P
[C#] Bitwarden server repository is probably one of the cleanest (non-novel) solution architectures I have seen so far. I always point people to it as learning material for structuring the code. It is not the most minimalistic but I feel like it strikes very good balance and does not follow blindly all the """fancy""" OOP patterns people should never use anyway.
Otherwise, I can see why people are burned, average Java/C# codebases look abysmal and written without understanding of (not) using heaps of mediator/factory/adapter/provider classes.
The various flavors of Forth all qualify. They are great examples of how to bootstrap towards a powerful abstraction, starting from a relatively simple context. The 80% of the 80/20 rule here comes from "writing a Forth" being an engaging learning experience.
For anyone who would like to do that, I recommend looking up one of the old standards(FIG-FORTH, FORTH-79, FORTH-83) and implementing the words in them with whatever tools and languages you like. You will hit a point where your early assumptions about the implementation are wrong. Keep going, get it to the point where you are capable of using the metaprogramming words.
There were 3 different libraries that impressed me:
1. The SunOS headers. Couldn't see the code but the number of header files was small enough in the 4.x Sun libraries that you could read them all. Mostly the documentation was terse but information dense.
2. The TeX sources. Knuths literate programming seems like such a missed opportunity.
3. ParcPlace VisualWorks. Due to the nature of Smalltalk you could read all the source code, learn object patterns directly from the people who invented it. A great learning experience when transitioning from C and so much better than the cfront based C++ hack.
What I find to be elegant in a codebase is where the chosen abstractions or seams that separate subdomains/concerns is well chosen that each is handled mostly in one place without a lot of ceremony or machinery. I would call these 'well factored' for factors which are domain-specific.
Each language has different ways that may lend itself as part of this shaping, but I like being able to think of this as something to look for when reading and strive for when writing, irrespective of the language at-hand.
Back when I first was learning about GraphQL in 2016, I remember thinking the reference implementation in JavaScript was extremely clear, easy to read, and well organized. It had a "wow, I wish all the code I read was this good" feel to it for me.
The TurboVision library that came with Turbo Pascal was awesome. Borland really had their shit together back in the day. Then they got greedy and overpriced their product, and killed the community.
C++: ClickHouse. It is very readable and easy to navigate. Call stacks that you pick up in logs are very descriptive, and you can easily tell what went wrong.
Not sure if it's still the case but about 6 years ago Facebook's folly C++ library was something I'd point to for my junior engineers to get a sense of "good" C++ https://github.com/facebook/folly
> But I believe the project is much cleaner and frankly better to understand than all other projects i've encountered for this size. I'm using DDD, so DDD knowledge is a requirement to navigate this in a breeze :) :
- https://snipboard.io/D03VWg.jpg - General overview of the architecture. Small fyi: Connectors => Autogenerated nugets to call the api's
- https://snipboard.io/lE9vcK.jpg - How specifications are translated to the infrastructure ( here I'm using EF, so I'm using Expressions a lot), but plain old SQL is also supported. A query is basically a list of AND/OR Specifications where a hierarchy is possible. This would translate to "(QUERY 1 ) AND ((QUERY 2) AND (QUERY 3))" in the Infrastructure layer.
- https://snipboard.io/7rVBpk.jpg - . In general, i have 2 List methods ( one for Paged queries and one not for Paged queries)
Additional fyi: Is V2, so has some legacy code. Uses my own STS. Has 2 gateways ( the ShopGateway that is used to develop new sites and the BackendGateway for the Backend). Enduser frontend is in MVC for SEO purpose, Customer backend is in Angular ( SPA). The basket is a NoSql implementation on top of SQL server.
The enduser frontend supports a hierarchy of themes ( so it's insanely flexible to create variations of pages for other clients).
There are more projects involved outside of this solution, eg. nuget repo's usable accross solutions (JWT, Specifications, ...) and "plugins" for a standalone project that is installed for end-users for syncing local data. So it's +101 projects :)
Just a shame that while i gave a pretty clear technical description on the "why i think so".
Nobody of the downvoters actually cared to give a actual technical counter argument or even did a test with a technical question... Instead just a reply with a partial movie script...
What else my own, Java, coding for over 50 years. If YOU can't figure
out what your own code is doing after ten years of not looking at it
then nobody else can either. Hint, Comment your thoughts as much as
possible, to make things clear when there not to you.
Format just like a book. Use full text variables, methods, class names.
Don't start a project until you define your formatting. Stick to it!
Do this and your documentation will be easy.
A great example of how NOT to write Java. You say absolutely nothing with a whole lot of extra words.
For example:
//==============================================================
// Ajqvue Constructor
//==============================================================
public Ajqvue()
The constructor definition is already clear, I don’t need a big header telling me what a constructor is.
Instead, use comments generously where needed - for example, if you have a piece of business logic, a comment explaining the intent behind it can help the maintainer (likely you) a year down the road. What I mean by this, is that what your code DOES should be self evident - but documenting the business decision behind the implementation has done wonders for me.
The getWebsite method comment says it returns the version. That's an example of how not to comment - totally pointless and misleading if it diverges from the code. The code is nice and clear without the comments.
This is pretty good! I'd be happy to work with you :-)
There are undoubtedly some pointless comments, but there are some good ones too, and the code is understandable. I think the sibling comments are being overly harsh and are zeroing in on single examples and missing the forest for the trees.
I suspect recommending your own code as an example of the most elegant codebase is triggering to others, so there's probably a negative initial reaction and probably a lot of people clicking your link so they can point out why you're wrong
Good structure overall and appreciate the summary at the top. For the inline comments more "why" and less "what" would give higher signal-to-noise as a large percentage of that content is adding nothing that basic Java syntax and variable names don't already tell you.
In the decades Java sources have been available, any of the kazillion junior programmers could debug-step into java.* and see exactly what's happening -- progressive disclosure at its finest for building expertise.
Most other languages have a hard boundary, so the roots of language are a matter of conceptual documentation and experience. Java also offers that fly-over knowledge, but when problems arise, programmers love knowing exactly and seeing directly.
Personally, in a pinch I prefer the actual to the elegant.