Threads for bilinguliar

  1. 1

    Panchan is written in Golang, and utilizes its built-in concurrency features to maximize spreadability and execute malware modules

    I’m naive in this domain. Is it unusual for worms to be written in high-level, modern languages? If so, why?

    1. 4

      I think because of the size of the executable and memory requirements. According to the article, this Go worm is already 30MB! This has to do with the runtime that is embedded into the binary and tons of dependencies.

      1. 3

        I believe that golang is becoming popular in malware. It’s extreme portability and the ease at which you can compile cross platform makes it perfect for broad attacks.

        So many vulnerable devices have at least a few hundred megs of space and high speed internet is practically global now days.

        1. 1

          I think it’s a bit of a mix. Often high-level languages used are more the type of “native” scripting languages for target, either because it’s part of getting the exploit to run at all (powershell, VBA, …) or because common on the platform (powershell, Python, …). Whereas for more low-level attacks the exploits are developed by people that have skills in more low-level languages and are happy to use those.

          Although maybe with malware-as-a-service the core and payload modules might be written in a higher-level language and only the pieces that need to be low-level are C/C++/… ? Not sure, but I bet there’s analysis of samples of those around.

        1. 36

          I owe Atom the decision of starting using Vim. I used it around 2015 and it crashed when opening big JSON files. Tired of it, looked for and editor which didn’t freeze my computer when dealing with big files and ended up learning Vim and I have not stopped since then (I guess I don’t know how to exit :^) )

          1. 3

            nvi is the next step

          1. 1

            I would love to buy the same but with Meshtastic.

            1. 3

              I expect this will eventually replace git client for some of us who are frustrated by the unnecessary complexity of the existing solution.

              The last time I checked, this project lacked a simple migration guide: what you did in git VS what you do in got. But now, the manual page has a lot of examples, and I am willing to give it a try!

              1. 3

                it’s simpler to just use git

                1. 1

                  or fossil

                2. 2

                  This project’s target demographic are people using CVS (or maybe Subversion), so I’m not surprised there’s no migration guide from Git.

                1. 1

                  Great talk! Hard to find examples that are not related to games. DoD movement deserves to become more popular.

                  1. 5

                    I expected to see The Game of Life there as well. Now I am on a mission to disturb that space.

                    1. 9
                      1. 7

                        He ripped that first-mover advantage right from my hands.

                        1. 4

                          Unfortunately, you can’t modify the simulation by checking boxes…

                      1. 71

                        I think it depends heavily on who you are trying to teach. I strongly believe the goal should be to ignite curiosity and empower someone to follow where that curiosity leads them. For one person, this might be writing some C to run on a microprocessor to read data from a sensor. For another, it might be building a Django app. Figuring that out is the hard part, in my opinion. Once you do that, things will fall into place for a while.

                        1. 15

                          Adding to that, motivation is always key when learning anything, and working on stuff you want to work on is the best way to be motivated.

                          1. 8

                            A corollary here is that the easier it is to find an engaging project to write in a language, the easier it is to learn a language. That’s why I feel like the best way to proceed when teaching kids is to start with making a game. Of course, every kid is different; some kids may be able to sustain interest just on the basis of a fascination with logic alone (like Bryan Cantrill in the OP) but if you assume everyone thinks this way going in you’re just going to end up with frustration. Building a game is a starting point that will resonate with a much wider audience!

                            1. 3

                              Some random musings:

                              My first program was to sort the list of games I had; every floppy disk we had contained a bunch of games, something like 10-20 of them. And “I want to play game foo” meant going through the hundreds of disks we had to find it. I numbered the disks and wrote down which games it had, but a handwritten notebook isn’t actually all that much easier, whereas a sorted list is.

                              I remember typing ZZZZZZZZZZZZZ at some point; it was slow as hell, probably somewhere between O(omg) and O(fucked). But it did work and solved a real practical problem I had, and a 12-year old me was very proud of it and happy.

                              In spite of all the new languages, the internet, a plethora of books and courses, etc. I sometimes feel that getting started is, in a way, harder today than it was when I was young all those years ago. You just don’t really run in to these kind of fairly simple practical problems any more: you’d just use a spreadsheet or something like that today. Of course that’s not a bad thing as such, but it does mean there are far fewer problems to solve. I sometimes wonder if I ever would have gotten in to programming if I was born 25 years later.

                              After we got a “proper” Windows 95 PC I stopped programming, as I didn’t really know how to and was so much harder to get started. The MSX just booted in a BASIC environment and you could program. I didn’t know about Python or Perl and such, and mucking about with Visual Studio was complicated and I didn’t really understand it (it didn’t help that the “Teach yourself C++ in 10 minutes”-book I got from the local bookstore was beyond horrible). I got back in to it a few years later by making some mods for Unreal and Deus Ex (which resulted in avoiding OOP, and inheritance in particular, for years to come), and after I started using Linux and FreeBSD I discovered Perl and Python and that you didn’t need an expensive (pirated of course) copy of Visual Studio to prmeansogram on modern machines. Things have certainly improved in that area.

                              1. 3

                                I have a similar story where I got started on QBasic and loved the immediacy but I hated DOS. When I learned to program a “proper” GUI for my Mac I got so bummed out by the tedium that I stopped programming for years.

                                That’s part of why I’m excited about environments like TIC-80. They may never ship with the OS, but it has all the immediacy and “batteries included” and none of the “faff around with the environment before you can get it working” problems that most beginners face nowadays.

                              2. 3

                                A corollary here is that the easier it is to find an engaging project to write in a language, the easier it is to learn a language.

                                For some people (i.e. me) this can be tricky. My first steps in programming were in Basic on a ZX Spectrum. Once we got a PC, it was natural to continue with QBasic or something like that there. But I actually stopped for a while then. Because while I could write programs, they would need to run in the Basic interpreter. And therefore, they were not “real” programs, like the other one I had on the PC. And if it was not “real” then I didn’t want to waste time on it. It felt more like making toys, in a playground called Basic.

                                Thinking about it now, that was apparently the first manifestation of the programming me that wants to avoid lock-ins and resents unnecessary dependencies.

                            2. 8

                              This is roughly what I came to say. I dropped out of c++ focused cs because the projects weren’t engaging enough to suffer long projects while working nights.

                              Later, I crawled through glass to pick up php for some projects that interested me.

                              I imagine not everyone has the luxury of finding that driving project to learn through… But I still suspect it’s best to follow curiosity if at all possible?

                              1. 4

                                Same - I dropped out of my C++ classes, in fact I despised coding until ten years after college. A combination of luck and opportunity changed my life, and I learned Rails. I actively despise the approach in Rails apps now, but I feel like for the place and time learning a web framework which forced me to “just build a cool website” was a life changing and positive experience. I’m now working for a big tech company and life is more or less ok.

                                1. 4

                                  I have a very similar story. Grew up with BASIC, “learned” C++/Java at university, hated that, stopped programming for maybe 5 years, got sucked back in by Python, became a professional programmer nine years after graduating with a CS degree.

                                2. 1

                                  Just great…. C++ is my next class!!!! I still keep asking myself if I enjoy programming or not, I’ve only written one “real” program in my entire life and it was in BASIC back in the Commodore 64 days. I was an avid radio scanner buff (still am to this day) and spent I don’t know how many painstaking hours writing out a database from a copy of Police Call all so I could query my computer vs. look it up in a book!

                                  I have personally struggled in this space, I’ve spent countless hours and money on books, courses etc trying to learn C/C++ but just doesn’t jive with me for whatever reason, and it seems like I’m not alone. Perhaps it will “click” for me someday.

                                  1. 1

                                    I mean, I wouldn’t say it has to be bad.

                                    It wasn’t the C++ that I didn’t like, it was being run ragged by long debug sessions on things I didn’t care about like a program to play tic-tac-toe. If I had cared about programming or the language for its own sake, that might have changed the dynamic a little.

                                    ~7 years later (after the PHP project opened my eyes a bit to how code could fit into my projects) the language I ended up really cutting my teeth on was LPC, a C-alike used to write LD/LPMuds. It took a while for things to really click, so it helped to be working on something I found fun.

                                3. 5

                                  Adding to that, it is good to begin solving a real problem from the get-go. Working on an imaginary problem may not sparkle authentic and sustainable curiosity.

                                1. 2

                                  Talking about CPU-friendly code, is there a good example of a Go application written in a data-oriented design paradigm? Something that Mike Acton and Stoyan Nikolov described in their talks concerning C++.

                                  1. 6

                                    go-geom uses a linear layout for its coordinates, which makes it 30% faster than the equivalent C library in benchmarks, see https://github.com/twpayne/go-geom/blob/master/INTERNALS.md#efficient.

                                  1. 5

                                    My path was:

                                    1. Ubuntu + Gnome
                                    2. Debian + Gnome
                                    3. Debian + i3wm
                                    4. Debian + dwm
                                    5. OpenBSD + dwm

                                    I am thankful to i3 for being a gateway drug.

                                    1. 18

                                      The whole damn thing.

                                      Instead of having this Frankenstein’s monster of different OSs and different programming languages and browsers that are OSs and OSs that are browsers, just have one thing.

                                      There is one language. There is one modular OS written in this language. You can hot-fix the code. Bits and pieces are stripped out for lower powered machines. Someone who knows security has designed this thing to be secure.

                                      The same code can run on your local machine, or on someone else’s machine. A website is just a document on someone else’s machine. It can run scripts on their machine or yours. Except on your machine they can’t run unless you let them and they can’t do I/O unless you let them.

                                      There is one email protocol. Email addresses can’t be spoofed. If someone doesn’t like getting an email from you, they can charge you a dollar for it.

                                      There is one IM protocol. It’s used by computers including cellphones.

                                      There is one teleconferencing protocol.

                                      There is one document format. Plain text with simple markup for formatting, alignment, links and images. It looks a lot like Markdown, probably.

                                      Every GUI program is a CLI program underneath and can be scripted.

                                      (Some of this was inspired by legends of what LISP can do.)

                                      1. 24

                                        Goodness, no - are you INSANE? Technological monocultures are one of the greatest non-ecological threats to the human race!

                                        1. 1

                                          I need some elaboration here. Why would it be a threat to have everyone use the same OS and the same programming language and the same communications protocols?

                                          1. 6

                                            One vulnerability to rule them all.

                                            1. 2

                                              Pithy as that sounds, it is not convincing for me.

                                              Having many different systems and languages in order to have security by obscurity by having many different vulnerabilities does not sound like a good idea.

                                              I would hope a proper inclusion of security principles while designing an OS/language would be a better way to go.

                                              1. 4

                                                It is not security through obscurity, it is security through diversity, which is a very different thing. Security through obscurity says that you may have vulnerabilities but you’ve tried to hide them so an attacker can’t exploit them because they don’t know about them. This works as well as your secrecy mechanism. It is generally considered bad because information disclosure vulnerabilities are the hardest to fix and they are the root of your security in a system that depends on obscurity.

                                                Security through diversity, in contrast, says that you may have vulnerabilities but they won’t affect your entire fleet. You can build reliable systems on top of this. For example, the Verisign-run DNS roots use a mixture of FreeBSD and Linux and a mixture of bind, unbound, and their own in-house DNS server. If you find a Linux vulnerability, you can take out half of the machines, but the other half will still work (just slower). Similarly, a FreeBSD vulnerability can take out half of them. A bind or unbound vulnerability will take out a third of them. A bind vulnerability that depends on something OS-specific will take out about a sixth.

                                                This is really important when it comes to self-propagating malware. Back in the XP days, there were several worms that would compromise every Windows machine on the local network. I recall doing a fresh install of Windows XP and connecting it to the university network to install Windows update: it was compromised before it was able to download the fix for the vulnerability that the worm was exploiting. If we’d only had XP machines on the network, getting out of that would have been very difficult. Because we had a load of Linux machines and Macs, we were able to download the latest roll-up fix for Windows, burn it to a CD, redo the install, and then do an offline update.

                                                Looking at the growing Linux / Docker monoculture today, I wonder how much damage a motivated individual with a Linux remote arbitrary-code execution vulnerability could do.

                                                1. 1

                                                  Sure, but is this an intentional strategy? Did we set out to have Windows and Mac and Linux in order that we could prevent viruses from spreading? It’s an accidental observation and not a really compelling one.

                                                  I’ve pointed out my thinking in this part of the thread https://lobste.rs/s/sdum3p/if_you_could_rewrite_anything_from#c_ennbfs

                                                  In short, there must be more principled ways of securing our computers than hoping multiple green field implementations of the same application have different sets of bugs.

                                                2. 3

                                                  A few examples come to mine though—heartbleed (which affected anyone using OpenSSL) and Specter (anyone using the x86 platform). Also, Microsoft Windows for years had plenty of critical exploits because it had well over 90% of the desktop market.

                                                  You might also want to look up the impending doom of bananas, because over 90% of bananas sold today are genetic clones (it’s basically one plant) and there’s a fungus threatening to kill the banana market. A monoculture is a bad idea.

                                                  1. 1

                                                    Yes, for humans (and other living things) the idea of immunity through obscurity (to coin a phrase) is evolutionarily advantageous. Our varied responses to COVID is one such immediate example. It does have the drawback that it makes it harder to develop therapies since we see population specificity in responses.

                                                    I don’t buy that the we need to employ the same idea in an engineered system. It’s a convenient back-ported bullet list advantage of having a chaotic mess of OSes and programming languages, but it certainly wasn’t intentional.

                                                    I’d rather have an engineered, intentional robustness to the systems we build.

                                                    1. 4

                                                      To go in a slightly different direction—building codes. The farther north you go, the steeper roofs tend to get. In Sweden, one needs a steep roof to shed show buildup, but where I live (South Florida, just north of Cuba) building such a roof would be a waste of resources because we don’t have snow—we just need a shallow angle to shed rain water. Conversely, we don’t need codes to deal with earthquakes, nor does California need to deal with hurricanes. Yet it would be so much simpler to have a single building code in the US. I’m sure there are plenty of people who would love to force such a thing everywhere if only to make their lives easier (or for rent-seeking purposes).

                                                      1. 2

                                                        We have different houses for different environments, and we have different programs for different use cases. This does not mean we need different programing languages.

                                                  2. 2

                                                    I would hope a proper inclusion of security principles while designing an OS/language would be a better way to go.

                                                    In principle, yeah. But even the best security engineers are human and prone to fail.

                                                    If every deployment was the same version of the same software, then attackers could find an exploitable bug and exploit it across every single system.

                                                    Would you like to drive in a car where every single engine blows up, killing all inside the car? If all cars are the same, they’ll all explode. We’d eventually move back to horse and buggy. ;-) Having a variety of cars helps mitigate issues other cars have–while still having problems of its own.

                                                    1. 1

                                                      In this heterogeneous system we have more bugs (assuming the same rate of bugs everywhere) and fewer reports (since there are fewer users per system) and a more drawn out deployment of fixes. I don’t think this is better.

                                                      1. 1

                                                        Sure, you’d have more bugs. But the bugs would (hopefully) be in different, distinct places. One car might blow up, another might just blow a tire.

                                                        From an attacker’s perspective, if everyone drives the same car, it the attacker knows that the flaws from one car are reproducible with 100% success rate, then the attacker doesn’t need to spend time/resources of other cars. The attacker can just reuse and continue to rinse, reuse, recycle. All are vulnerable to the same bug. All can be exploited in the same manner reliably, time after another.

                                                        1. 3

                                                          To go by the car analogy, the bugs that would be uncovered by drivers rather than during the testing process would be rare ones, like, if I hit the gas pedal and brake at the same time it exposes a bug in the ECU that leads to total loss of power at any speed.

                                                          I’d rather drive a car a million other drivers have been driving than drive a car that’s driven by 100 people. Because over a million drivers it’s much more likely someone hits the gas and brake at the same time and uncovers the bug which can then be fixed in one go.

                                            2. 3
                                              1. 1

                                                Yes, that’s probably the LISP thing I was thinking of, thanks!

                                              2. 2

                                                I agree completely!

                                                We would need to put some safety measures in place, and there would have to be processes defined for how you go about suggesting/approving/adding/changing designs (that anyone can be a part of), but otherwise, it would be a boon for the human race. In two generations, we would all be experts in our computers and systems would interoperate with everything!

                                                There would be no need to learn new tools every X months. The UI would familiar to everyone, and any improvements would be forced to go through human testing/trials before being accepted, since it would be used by everyone! There would be continual advancements in every area of life. Time would be spent on improving the existing experience/tool, instead of recreating or fixing things.

                                                1. 2

                                                  I would also like to rewrite most stuff from the ground up. But monocultures aren’t good. Orthogonality in basic building blocks is very important. And picking the right abstractions to avoid footguns. Some ideas, not necessarily the best ones:

                                                  • proven correct microkernel written in rust (or similar borrow-checked language), something like L4
                                                  • capability based OS
                                                  • no TCP/HTTP monoculture in networks (SCTP? pubsub networks?)
                                                  • are our current processor architectures anywhere near sane? could safe concurrency be encouraged at a hardware level?
                                                  • less walled gardens and centralisation
                                                  1. 2

                                                    proven correct microkernel written in rust (or similar borrow-checked language), something like L4

                                                    A solved problem. seL4, including support for capabilities.

                                                    1. 5

                                                      seL4 is proven correct by treating a lot of things as axioms and by presenting a programmer model that punts all of the difficult bits to get correct to application developers, making it almost impossible to write correct code on top of. It’s a fantastic demonstration of the state of modern proof tools, it’s a terrible example of a microkernel.

                                                      1. 2

                                                        FUD unless proven otherwise.

                                                        Counter-examples exist; seL4 can definitely be used, as demonstrated by many successful uses.

                                                        The seL4 foundation is getting a lot of high profile members.

                                                        Furthermore, Genode, which is relatively easy to use, supports seL4 as a kernel.

                                                  2. 2

                                                    Someone wrote a detailed vision of rebuilding everything from scratch, if you’re interested. 1

                                                      1. 11

                                                        I never understood this thing.

                                                        1. 7

                                                          I think that is deliberate.

                                                      2. 1

                                                        And one leader to rule them all. No, thanks.

                                                        1. 4

                                                          Well, I was thinking of something even worse - design by committee, like for electrical stuff, but your idea sounds better.

                                                        2. 1

                                                          We already have this, dozens of them. All you need to do is point guns at everybody and make them use your favourite. What a terrible idea.

                                                        1. 7

                                                          I agree with the comment; this is pretty light on how the author actually uses it.

                                                          1. 11

                                                            Yeah, it’s a really weird choice to conclude what is ultimately no more than a tutorial on setting up syntax highlighting in nano with a comment about how you’ve proven nano is as capable an editor as vim or emacs. It is and has for years been beyond me how nano could ever be useful outside of making trivial config file changes in a system you don’t have root access on – these days it seems more ubiquitous than vim or ed. I was hoping this article would clear that up.

                                                            Then again, maybe there’s nothing to clear up; maybe there really are people who have no further requirements for an editor than being able to type text and save it to a file. I don’t know.

                                                            1. 3

                                                              Some people can work perfectly fine with a minimal editor. For example Linus Torvalds with MicroEMACS.

                                                              1. 7

                                                                When I learned C, I decided to only use vi (not vim) without colors and without any custom config.

                                                                It’s a little weird at first, but the brain adapts (quickly) and recognizes the patterns. Now I don’t care which editor is on a system, or how it’s formatted on the web or in an e-mail.

                                                                1. 4

                                                                  Instead of vi, I use vis. But, in there, I do the same: I disable the syntax highlight, and I only use the default settings of the editor.

                                                                  I read somewhere, someday, that working with disabled syntax highlight makes the programmer more attentive to the code, and consequently make less mistakes.

                                                                  I actually never measured it, but I instinctively feel that I read more carefully the code base, and therefore I learned the code base I work on better than before.

                                                                  I also started to appreciate the [Open|Net]BSD code style, because it helps to work on this style, and to use default UNIX tools to find parts of the code I am interested at.

                                                                  In other words, it leverages UNIX as IDE.

                                                                  1. 2

                                                                    I am thinking about switching from vim to vi + tmux for Go.

                                                                    So far the most challenging was:

                                                                    • block edit;
                                                                    • go to definition;
                                                                    • copy/paste;

                                                                    Especially copy/paste. It turns out I heavily relied on yanking from one vim tab to another.

                                                                    1. 1

                                                                      Which vi? nvi?

                                                                      1. 1

                                                                        The version that came with the OS. Seems like nvi or at least based on nvi.

                                                                  2. 2

                                                                    It’s ubiquitous because it’s just what I’d expect from a debian system that some non-vim professional might have to administrate via CLI. And for anything that isn’t changing configs on remote systems / rescue mode I’ve got an IDE or Kate if it’s supposed to be simpler.

                                                                1. 2

                                                                  We can admit that the whole web battle is lost and move to the gemini space.

                                                                  In a few years Chrome will run its own k8s instance and a Flutter v69.0.0 frontend will talk to it via gRPC and PubSub.

                                                                  1. 9

                                                                    The problem with Gemini is all the pages are made by other Gemini users and has useless syntax. The web wasn’t useful because it was for appealing to the aesthetics of chickenshit minimalists, it was useful because it had the ability to express information better through hypertext where Gopher wouldn’t.

                                                                    1. 6

                                                                      Why move to Gemini protocol? Why not just write the html you want to see, and have your friends do so too?

                                                                      1. 1

                                                                        Mainly because control over the web is already lost.

                                                                        How can we be sure that Chrome will not refuse to render vanilla HTML pages if there are no required attributes (Google Analytics UID or similar) in your head/body/anchor tags?

                                                                        Or better, imagine ANY ridiculous requirement that a single browser vendor may impose.

                                                                        Writing a whole new browser that implements the web stack is expensive and will take a lot of time. So Google has reliable protective moat there.

                                                                        Gemini contrary allows you to implement a client in a few hours, so the entry barrier is low.

                                                                    1. 26

                                                                      I’m a little bit suspicious of this plan. You specifically call out that you already have an anti-OOP bias to the point of even saying “no true Scotsman” and then say you plan to take anything someone sends you and denigrate it. Since no codebase is perfect and every practitioner’s understanding is always evolving, there will of course be something bad you can say especially if predisposed to do so.

                                                                      If you actually want to learn what OOP is like, why not pick up a known-good text on the subject, such as /99 Bottles of OOP/?

                                                                      1. 10

                                                                        I, for one, think this project seems very interesting. The author is correct that criticisms of OOP is often dismissed by saying “that’s just a problem if you don’t do OOP correctly”. Naturally, a response is to ask for an example of a project which does OOP “correctly”, and see if the common critiques still applies to that.

                                                                        Maybe the resulting article will be uninteresting. But I think I would love to see an article which dissects a particular well-written code-base, discusses exactly where and how it encounters issues which seem to be inherent in the paradigm or approach it’s using, and how it solves or works around or avoids those issues. I just hope the resulting article is actually fair and not just a rant about OOP bad.

                                                                        EDIT: And to be clear, just because there seems to be some confusion: The author isn’t saying that examples of good OOP aren’t “real OOP”. The author is saying that critiques of OOP is dismissed by saying “that’s not real OOP”. The author is complaining about other people who use the no true Scotsman fallacy.

                                                                        1. 7

                                                                          Explicitly excluding frameworks seems to be a bit prejudiced, since producing abstractions that encourage reuse is where OOP really shines. OpenStep, for example, is an absolutely beautiful API that is a joy to use and encourages you to write very small amounts of code (some of the abstractions are a bit dated now, but remember it was designed in a world where high-end workstations had 8-16 MiB of RAM). Individual programs written against it don’t show the benefits.

                                                                          1. 1

                                                                            Want to second OpenStep here, essentially Cocoa before they started with the ViewController nonsense.

                                                                            Also, from Smalltalk, at least the Collection classes and the Magnitude hierarchy.

                                                                            And yes, explicitly excluding frameworks is non-sensical. “I want examples of good OO code, excluding the things OO is good at”.

                                                                          2. 2

                                                                            Maybe the resulting article will be uninteresting. But I think I would love to see an article which dissects a particular well-written code-base, discusses exactly where and how it encounters issues which seem to be inherent in the paradigm or approach it’s using, and how it solves or works around or avoids those issues. I just hope the resulting article is actually fair and not just a rant about OOP bad.

                                                                            That’s exactly my plan. I have my biases and existing ideas, but I’ll try to keep it open minded and maybe through talking about concrete examples I will learn something, refine my arguments, or just have a useful conversation.

                                                                            1. 2

                                                                              The author is correct that criticisms of OOP is often dismissed by saying “that’s just a problem if you don’t do OOP correctly”.

                                                                              I know this may look like splitting hairs, but while “that’s only a problem if you don’t do OOP correctly” would be No True Scotsman and invalid, what I see more often is “that’s a problem and that’s why you should do OOP instead of just labelling random code full of if statements as ‘OOP’” which is a nomenclature argument to be sure, but in my view differs from No True Scotman in that it’s not a generalization but an attempt to make a call towards a different way.

                                                                              I agree that a properly unbiased tear-down of a good OOP project by someone familiar with OOP but without stars in their eyes could be interesting, my comment was based on the tone of the OP and a sinking feeling that that is not what we would get here.

                                                                              1. 1

                                                                                OOP simplifies real objects and properties to make abstraction approachable for developers, and the trade-off is accuracy (correctness) for simplicity.

                                                                                So if you would try to describe the real world in OOP terms adequately, then an application will be as complex as the world itself.

                                                                                This makes me think that proper OOP is unattainable in principle, with the only exception – the world itself.

                                                                              2. 3

                                                                                One could argue in favor of Assembly and still be right, which doesn’t make “everyone program should be written in Assembly” a good statement. It sounds, to me, like saying “English will never have great literature”. It doesn’t make much sense.

                                                                                Microsoft has great materials on Object-Oriented-Design tangled inside their documentation of .NET, Tackle Business Complexity in a Microservice with DDD and CQRS Patterns is a good example of what you want, but is not a repository I am afraid. Design Patterns has great examples of real world code, they are old (drawing scrollbars) but they are great Object-Oriented-Programming examples.

                                                                                Good code is good, no matter the paradigm or language. In my experience, developers lack understanding the abstractions they are using (HTTP, IO, Serialization, Patterns, Architecture etc.) and that shows on their code. Their code doesn’t communicate a solution very well because they doesn’t understand it themselves.

                                                                                1. 3

                                                                                  you plan to take anything someone sends you and denigrate it.

                                                                                  I could do that, but then it wouldn’t be really useful and convincing.

                                                                                  If you actually want to learn what OOP is like, why not pick up a known-good text on the subject, such as /99 Bottles of OOP/

                                                                                  Because no real program looks like this.

                                                                                1. 4

                                                                                  After driving with GPS, I have quickly degraded my natural ability to navigate. This is when I have decided to switch from an intelligent IDE to vim.

                                                                                  1. 3

                                                                                    After driving with a GPS that gets confused between left and right, I’ve lost my ability to feel confident in where I’m going. So I decided to pull out my vim setup to try and regain that confidence.

                                                                                    1. 3

                                                                                      More seriously, I’ve found one of the easiest solution to get some of that semblance of navigation back is to configure your application/device to always point north. It makes you more aware of your absolute position and alternate routes that will take you to the same spot.

                                                                                      I wonder what the IDE analogy is for this.

                                                                                      1. 1

                                                                                        Keep the high-end IDE in the toolbox, even if it isn’t your daily driver. The code generation and refactoring tools in Intelij let you perform miracles on the odd occasion they are needed. Honestly most people who use IDEs for everything don’t know how to use those tools.

                                                                                      1. 8

                                                                                        I can only say that it works so well that I never needed to understand it deeper. My biggest chore related to dependencies is to clean go.sum files from time to time. I use go mod tidy for that.

                                                                                        I also run local go modules proxy (Athena) at home simply because I often update dependencies in multiple projects.

                                                                                        1. 6

                                                                                          My biggest chore related to dependencies is to clean go.sum files from time to time. I use go mod tidy for that.

                                                                                          You do not need to clean go.sum. That file is an (almost) append-only log of checksums of modules that may be considered when building your dependency graph, and it’s used only to detect corruption or malfeasance. It’s not a lock file, and it doesn’t really represent the size or state of your dependency graph. (At best, it has a correlative relationship.) You should check it in for safety reasons, but there is basically no reason you should ever look at it, or care how big it is.

                                                                                          1. 1

                                                                                            Thanks, it is good to know! I believe it is just a personality deformation, to delete lines that are not required.

                                                                                            1. 2

                                                                                              I don’t think “required” is actually well-defined, when it comes to lines in go.sum.

                                                                                              1. 2

                                                                                                In a situation when you were using foo@v1.0.0 and then updated to v1.0.1. The record in go.sum related to the older version does not serve any purpose. Is this a valid assumption?

                                                                                                1. 1

                                                                                                  Well, does a transitive dependency depend on v1.0.0? Depending on how optimized the modules tool is, it could still need to download and evaluate it.

                                                                                                  1. 2

                                                                                                    I see this makes sense, and my understanding was the same.

                                                                                                    I have slowly navigated towards a minimal possible number of dependencies in my code. Bumping a single dependency typically (but not constantly) leaves me with just one version required.

                                                                                            2. 1

                                                                                              IIRC go.sum should only “shrink” when you switch or remove a dependency, right?

                                                                                              1. 2

                                                                                                I don’t think you can make very many authoritative claims about the relationship between your dependency graph and the contents of go.sum. The rules that govern that relationship change from version to version.

                                                                                            3. 5

                                                                                              I can only say that it works so well that I never needed to understand it deeper

                                                                                              Yup. I remember fiddling about with packages in Node and Python so much, but never really had to worry in Go.

                                                                                              With Go, there was the initial occasional issue with people changing the capitalisation of their usernames (and causing package breakages), or initial teething issues, but when everyone follows the rules (and most do), it works fine!

                                                                                            1. 6

                                                                                              I wish this included some explanation of why these are useful or explanations of why they are. Like, why use zerolog over logrus/zap/whatever? Why use gorilla/mux over gin or go-chi or the standard library? Why have that overly-complex unique code thing to determine where a logged error is thrown instead of making sure your errors have stack traces?

                                                                                              1. 4

                                                                                                I’m not the author of the post, but I can try to answer some questions:

                                                                                                Like, why use zerolog over logrus/zap/whatever?

                                                                                                zerolog and zap is what the author of logrus admit he would write if he wrote logrus/v2. zerolog claims to be a “better” version of zap (there are claims of performance improvement on other people’s computers)

                                                                                                Why use gorilla/mux over gin or go-chi or the standard library?

                                                                                                gorilla/mux is much lightweight as opposed to gin which has renderers, etc… Also, there are claims of very high performance on other people’s computers. With gorlla/mux you can plug your own json de-/serialization library which is faster than gin’s.

                                                                                                Why have that overly-complex unique code thing to determine where a logged error is thrown instead of making sure your errors have stack traces?

                                                                                                ¯\(ツ)/¯ No idea… The unique code approach feels very hacky and brittle to me.

                                                                                                1. 3

                                                                                                  I would even suggest “httprouter” as a more lightweight alternative to gorilla/mux.

                                                                                                  1. 2

                                                                                                    Most “higher level” Go routers are probably based on it anyways.

                                                                                                  2. 1

                                                                                                    We use unique logging codes for our logs, and it makes it easier to locate a particular statement in either the logs, or the source code. Now, we generate the unique code by hand, but it’s not a horrendous issue for us (we have a separate document that records each logging statement).

                                                                                                  3. 1

                                                                                                    I’d be curious to know the best practices for annotating errors with stack traces. Any good library suggestions?

                                                                                                    1. 3

                                                                                                      github.com/pkg/errors has some nice helpers, as described in its documentation. The issue is that it requires changing your code to using errors.Errorf() instead of fmt.Errorf().

                                                                                                      Go2 will do it differently, but natively

                                                                                                      1. 3

                                                                                                        Also, errors.Wrapf is very useful when handling errors from packages which don’t use errors.

                                                                                                        1. 2

                                                                                                          You can wrap errors using fmt.Errorf() and the %w verb, and then later deal with them using errors.Is() or errors.As() and friends.

                                                                                                          1. 1

                                                                                                            That doesn’t give you stack traces though, correct?

                                                                                                        2. 2

                                                                                                          YES. This is probably my biggest issue with supporting production Go code. Errors are still too hard to locate.

                                                                                                          1. 1

                                                                                                            I personally use this to manage all that. If you use the errors.Wrap() function to wrap errors, it’ll add stack traces. And if you want to make a new error, the errors.New() function will also add a stack track where it was called. Then when you’re logging the error make sure it’s being logged in a way that will not just print the message. Most loggers should have a way to do that (I know zerolog and logrus do).

                                                                                                            1. 1

                                                                                                              Shameless plug for my errors library: https://pkg.go.dev/github.com/zeebo/errs/v2

                                                                                                              • captures stack traces, but only once even if wrapped multiple times
                                                                                                              • plays nicely with standard library errors package with errors.Is and errors.As
                                                                                                              • has a “tag” feature to let you associate and query tags with errors
                                                                                                              • helper to keep track of groups of errors
                                                                                                          1. 9

                                                                                                            My experience is that pure Go tests cover 99.9% of cases. Testify feels like an inability to adapt to a new language.

                                                                                                            1. 20

                                                                                                              My experience is that pure Go tests are obnoxious to write and debug. You have to tediously format debugging information yourself every time instead of having assert functions do that for you. That in turn makes failing tests harder to debug when the person before you didn’t bother doing it, or did so inconsistently.

                                                                                                              Worse, I’ve noticed that Go tests tend to assert the final results, but little in between. My tests usually assert every step of the way so I don’t have to spend time figuring out what went wrong. Perhaps if Go tests had a convenient assert, people would assert more.

                                                                                                              Asserts aren’t just for tests either. I use debug asserts all over my code. Asserts catch bad assumptions early, document those assumptions, and maintain their own freshness (they’ll fail when they’re wrong, unlike comments).

                                                                                                              1. 6

                                                                                                                Interesting, I do test intermediate state, but mostly errors.

                                                                                                                Formatting never was an issue for me. Sometimes comparing complex structs may be tedious. If reflect.DeepEqual does not help, than I use github.com/google/go-cmp and that is it.

                                                                                                                Other than that I do not have any issues with the testing package.

                                                                                                                1. 4

                                                                                                                  When a test is failing, do you ever printf debug? At some point I noticed that the majority of the time I add prints (or check values in a debugger), I’m looking for something specific that indicates the value is right or wrong. Asserts work perfectly for that, in tests or normal code.

                                                                                                                  1. 1

                                                                                                                    Most of the time failed test gives me enough information about the underlying issue, maybe because the scope of unit tests is somewhat limited.

                                                                                                                    If a test fails and I do not know the answer, I instrument my production code with a bunch of fmt.Printf statements, and it helps to find the issue.

                                                                                                                    I prefer limited output when it comes to debugging rather than overly verbose.

                                                                                                                    I see your point. I would imagine we have different coding styles.

                                                                                                                2. 6

                                                                                                                  I use https://github.com/google/go-cmp and the standard library testing package. I like the combo.

                                                                                                              1. 2

                                                                                                                I’ve been using a kanban-style workflow with a Trello board for the past few years, and it’s been pretty life-changing. It’s hard to remember how I used to get stuff done beforehand, in the dark days of a brief list scribbled on my whiteboard. I’ve completed 1028 tasks since June 2018.

                                                                                                                It’s more of a to-do list than a goal tracker… but I guess I could handle large goals with a new column for epics, and linking other cards to those. Or just a new label.

                                                                                                                For some goals, like eating a few portions of fruit or vegetables every day, I use beeminder. A daily recurring Trello card would be way too much overhead. I only have three of those, though.

                                                                                                                1. 1

                                                                                                                  I have started with a similar Kanban + Trello model. And just recently, I have moved to my own simplified “Get Things Done” solution. I have analyzed what parts of Trello I am using, and it turns out not many. So I have written my small tool using vanilla JS and Go.

                                                                                                                  Concepts:

                                                                                                                  • Each to-do item is a Project;
                                                                                                                  • Each project consists of Actions;
                                                                                                                  • I always split Project into the most simple atomic Actions;
                                                                                                                  • “Drafts” is for something that is not refined yet;
                                                                                                                  • “Active” is what I am going to do next, sorted by priority;
                                                                                                                  • “Next Actions” is a unique column that contains Actions from “Active” projects. The column gives me a list of simple things to do that moves me towards my goals;
                                                                                                                  • “Waiting” is for tracking delegated Actions;
                                                                                                                  • “Maybe” is for something that I want to do in the future, but it is not a priority. It is nice to have such inspirational goals separately and not at the bottom of your current Projects.
                                                                                                                  • “Done” is for completed items that I keep in this column for a week and then archive during the weekly board review;

                                                                                                                  Columns:

                                                                                                                  • Draft projects
                                                                                                                  • Active projects
                                                                                                                  • Next Actions & Waiting
                                                                                                                  • Maybe / One day
                                                                                                                  • Done

                                                                                                                  Why it is good for me:

                                                                                                                  • I dump every plan there and keep my head free from these thoughts;
                                                                                                                  • I analyze and refine every Project while I am fresh. Then I just complete primitive minimal Actions one after another during the day;
                                                                                                                  • I do not forget about household chores because I have both professional and personal projects on the board;
                                                                                                                  • I am not trying to sell myself any kind of golden plans and perks to boost my app with features that I do not use;
                                                                                                                  • It is not a universal Kanban board; contrary - it has a rigid structure, where I have one way of doing things;
                                                                                                                  • I own my data;
                                                                                                                  • I learned new things while implementing it;
                                                                                                                  • I am the only customer, so this is 100% product-market fit.
                                                                                                                  1. 1

                                                                                                                    Can I ask if you would dump this code under some permissive license? I’ve wanted something like this, and I promise not to ask for bug fixes

                                                                                                                    1. 1

                                                                                                                      UPD: @Vaelatern, I have deleted my first answer to your comment. I will try to provide more details in this reply.

                                                                                                                      I like the idea of open sourcing my tool. What currently prevents me from doing so is the storage backend. I am using Google Datastore, just because it was faster to do it this way. And I realize that it can be painful to deploy it now. I believe self-hosted version will do better with sqlite. I will implement it and then publish. Cheers.

                                                                                                                      1. 1

                                                                                                                        Lobste.rs replies are back! Have you decided not to do this, or is this still on your roadmap?

                                                                                                                        1. 2

                                                                                                                          Haha! Thanks for the reminder. I have successfully migrated the backend to SQLite. Some minor UI issues require a fix. But overall, I am ready to opensource it. BSD license.

                                                                                                                          I will write a short post about it 😁

                                                                                                                          1. 1

                                                                                                                            Huzzah!

                                                                                                                            1. 1

                                                                                                                              While I am working on release, you can check it here: https://getdone.club

                                                                                                                1. 13

                                                                                                                  What the colleague was proposing sounds like premature abstraction. I see this quite often, mostly with junior and medior programmers but sometimes in seniors too (hell, I still catch myself doing it) - they start inventing all kinds of abstractions and patterns “in case this code needs to change”. But the thing is, you never know how the code will change. The things you make configurable might actually never change, and the things you baked in as assumptions might change several times.

                                                                                                                  I find it’s best to write the code to be as straightforward as possible, so it’s easy to understand. Easy to understand code is easier to change too, because you’ll have an easier time figuring out the repercussions of your changes. Code that is factored in a way that makes it easy to understand and modify in various dimensions while still being efficient is the mark of a true craftsman.

                                                                                                                  As you get more experienced, you’ll notice the kinds of things that tend to change a lot (data models, database layouts etc) and you’ll develop a style that favors “premature abstraction” for these kinds of things. If you’re lucky, your past experience affects the future work too and you’ll be right on the money with your abstractions. They were still a bit premature in a way, but because you’re working in a similar context you see the same patterns over and over and you and your colleague will thank your prescience that allowed the easy changes.

                                                                                                                  However, be wary of carrying over these abstractions to other kinds of work, as your hard-won experience will actually betray you. For example, people working on frameworks and libraries tend to favor decoupling database code so that it can work on multiple databases. This is often the right thing to do for libraries, but in end-products it just makes code needlessly complex and slow - there it makes more sense to maximally leverage the features of the database you chose in the first place.

                                                                                                                  1. 6

                                                                                                                    I agree with all sjamaan has written. Also, I want to add:

                                                                                                                    What the colleague was proposing sounds like premature abstraction.

                                                                                                                    I call that YAGNI.

                                                                                                                    I was going to joke by starting my comment as “I stopped reading at ‘My initial proposal was to add a class…’”. I was a heavy Python class user (inherited from University Java class, and the Python community), now that I have seen how much pain it is, and how much easier it is to work and debug with simple data types and functions (possibly passing function as arguments to do inversion of control).

                                                                                                                    I did not write “you do not need classes or disjoint types, and anything beyond dict and list is overkill”. My current approach is to start new code as simple as possible but not simpler. To be able to grasp that, I learned standard Scheme that does not have OOP builtin.

                                                                                                                    I quote the great last sentence of the previous comment that is my approach to build “abstractions” on top of SQL databases:

                                                                                                                    in end-products it just makes code needlessly complex and slow - [in end products] it makes more sense to maximally leverage the features of the database you chose in the first place.

                                                                                                                    1. 1

                                                                                                                      The story is slightly editorialized to (hopefully) by applicable to a larger audience. The actual language being used doesn’t even have classes. In general I agree that OOP is a tool to use sparingly.

                                                                                                                      1. 1

                                                                                                                        (opinion) OOP is a great tool for API discovery

                                                                                                                        I’ve not found it useful for much else tbh.

                                                                                                                    2. 4

                                                                                                                      I agree that what my colleague proposed was premature abstraction, at least from my perspective. But as you note, oftentimes experience will favor certain premature abstractions. This colleague was also at a high senior level (at least in title), so I like to give benefit of the doubt that they know what they are doing.

                                                                                                                      What is interesting is that “code as straightforward as possible” also suffers from ambiguity. From your comments, I believe you and I agree on what that looks like, but someone from a different background may completely disagree. My colleague might argue that their proposal was very straightforward! The absolutely fascinating bit is that “decoupled code” and “code that is simple” is something we all know as the goal, but the true definitions of what these mean are not actually defined.

                                                                                                                      I thought it was just so utterly strange that two entirely different approaches can both be justified with the same reasoning – and is there any way to “prove” that one approach is more correct than the other? Or are we just basing it all on our personal background experience?

                                                                                                                      1. 4

                                                                                                                        I don’t think you can “prove” that one approach is better/more correct than the other, because that’s highly subjective. Everybody will be bringing in different baggage. My gut says that “straightforwardness” as I call it should be measurable - the less indirections, classes, methods and conditionals you have, the more straightforward the code is.

                                                                                                                        But even this relatively objective measure can be perverted, I’m sure, because programmers are just so damn good at that. Just think “code golf” to reduce the LOC count - that doesn’t necessarily make it more readable/straightforward.

                                                                                                                        1. 3

                                                                                                                          I lean towards agreeing that “proving” one approach over the other is impossible. Then I guess the question is, if everyone has different, subjective, ideas of what “straightforward code” and “decoupled code” is, does it even make sense to have “straightforward and decoupled code” as the north star for software engineering? If none of us agree on where that north star is in the sky, we’re all going in different directions with entirely different maps of the world.

                                                                                                                          This is mostly just a philosophical question, one which I find myself considering. The engineer/scientist in me truly wants to define what good code looks like, but if its fundamentally a problem about people then that is clearly impossible.

                                                                                                                          1. 3

                                                                                                                            It’s a very good question indeed. I think maybe it’s much less important as to where your particular north star is than to have a consistent vision of where that star should be in a given team/project. That way, you get a consistent codebase that perhaps some onlookers find horrible and badly engineered, but everyone on the team agrees is a joy to maintain.

                                                                                                                            At least in my own experience, in a team where people are aligned on a certain style of engineering, you get a codebase that has an internal coherency. If different parts are done by people with different viewpoints, you get a Frankenstein monster that has no sense of identity. I’ve seen this happen, and it can be very difficult to reconcile this without somehow “enforcing” one view on those that disagree. And even talking about it can be difficult, because it’s something that’s very difficult to adequately put into words.

                                                                                                                            I think this is something that “style guides” try to do but fail at miserably because they’re only focused on the superficial syntactical details. But choosing (for example) whether to use interfaces or callbacks in a codebase goes much more deeply than that. And to make matters worse, there may be cases where there’s a good technical reason to deviate from the common convention.

                                                                                                                            1. 2

                                                                                                                              That is a good point, perhaps the only thing that does matter is what the team agrees on. Being aligned on the north star is certainly important, but where the north star is might not be. Definitely something I’m going to need to spend some time mulling over.

                                                                                                                              Then there is the question of whether a particular north star will “dominate” so to speak. For instance, complex abstractions are oftentimes difficult to replace while more straightforward approaches are oftentimes easier. The paradox is that straightforward code is usually refactored until it is complicated and difficult to change, while complicated code remains complicated. Does a team or project’s north star inevitably drift towards complicated over time? My instinct says yes, which I feel has some interesting consequences.

                                                                                                                              1. 1

                                                                                                                                Does a team or project’s north star inevitably drift towards complicated over time? My instinct says yes, which I feel has some interesting consequences.

                                                                                                                                hm, I’d have to agree that, in general, products tend to become more complicated due to the pressures from changing requirements, and the code follows suit. With one caveat: I’ve seen some refactorings that made needlessly complicated code much clearer (but possibly more abstract and complex to understand from scratch). Sometimes all it takes is some time away from the code to realise how it can be made simpler by finding the right abstraction for that particular part of the code. And sometimes it takes multiple iterations of refactorings in which one realises that eventually entire parts can simply be dropped.

                                                                                                                                1. 2

                                                                                                                                  As an aside, I think the fact that products will grow more complex over time is a great reason not to start out making things complex right away. That complexity will probably be in different places than you expect, just like performance bottlenecks will be in different places than you expect. So premature abstraction is like premature optimization in that sense, and also in the sense that it is silly to design code in a way that you know will be slow/difficult to adapt to changing requirements - it just takes a lot of experience to see where to apply optimization and abstraction ahead of time.

                                                                                                                            2. 1

                                                                                                                              In the long term this can be measured in money: how much product earns and how much it costs to support it. Earnings incorporate values like customer satisfaction. Spends can tell about team velocity and maybe even employee churn.

                                                                                                                      1. 7

                                                                                                                        I can relate to this topic. Background: I have started with Java and later transitioned to Go. At this point, I have more Go experience than Java. I will concentrate on these two languages. But I believe that concerning the topic we can roughly compare two groups of languages: (Go, C, Rust, etc.) and (Java, .NET, Ruby, etc.).

                                                                                                                        I have noticed that traditions (or cargo-cult) in Java are solid. You always apply some layered architecture, you always use interfaces, and you always test against your mocks. Often you do not ask a lot of questions with well-established legacy corporate systems. And very often, your framework will dictate how to structure your code.

                                                                                                                        In Go, and I believe in C as well, things are more straightforward. Due to the niche (infrastructure in case of Go) that language occupies, in most cases, you have a minimal system that is fine-tuned to solve one particular problem, interacting with well-known external systems. In Go, you declare an interface only when you can not avoid having one. Overall approaches are much more practical, and this allows you to write simpler code. If there is no framework, you have more freedom. In Go, the standard library is your framework.

                                                                                                                        Sure, nowadays, we have more extensive Go applications that adopted some enterprise patterns. Still, an excellent project will strike you as a minimal sufficient implementation to solve concrete tasks.

                                                                                                                        Comparing my experiences with both approaches: you get a more reliable solution when you test against the real deal (DB, queue, fs, etc.) and avoid extensive use of mocks. You get a more straightforward and more readable solution when you use fewer abstractions. Simple code makes handling (rare) incidents at 3 AM way easier.

                                                                                                                        The enterprise approach gives you the flexibility to switch vendors rapidly, a requirement that can not be ignored in the real world.

                                                                                                                        There is a middle ground when abstraction and complexity are extracted into a separate library and maintained independently. Then you can have both: simplicity and flexibility. From my experience, “gocloud.dev” is an excellent example of such an approach. This set of libraries abstracts away different cloud implementations for you. You can keep your applications small and simple and still have an opportunity to switch vendors and perform tests.

                                                                                                                        To conclude, I want to say that collaboration between people with radically different views often makes the product better. It is hard, and staying respectful is the key (reminder to myself).

                                                                                                                        1. 4

                                                                                                                          Thanks for your thoughts! I think you capture the trade-offs between the two approaches well, and I agree, there do seem to be two groups of languages in this regard.

                                                                                                                          I have noticed that traditions (or cargo-cult) in Java are solid.

                                                                                                                          I have found this as well. Every colleague I have worked with that had an extensive Java background knew the name of every design pattern, and would describe all code and approaches as combinations of these. Personally, I’ve just understood the concepts behind the various design patterns, otherwise I just apply them where they fit naturally (only remembering the name of a tricky few which are handy for explaining to junior engineers so they can research them more). Completely different approaches!

                                                                                                                          To conclude, I want to say that collaboration between people with radically different views often makes the product better. It is hard, and staying respectful is the key (reminder to myself).

                                                                                                                          I couldn’t agree more. The combination of different views and backgrounds is incredibly important for a robust product. Staying respectful, identifying trade-offs, and justifying decisions (without cargo-culting in either direction) is extremely difficult and what I think is the true mark of an expert.