Ask HN: Concepts that clicked only years after you first encountered them?
I'm reading Petzold's Code [1], and it dawned on me that I didn't understand logic gates intuitively until now. I took a Computer Architecture course back in college, and I understood what logic gates meant in boolean algebra but not empirically. Petzold clarified this for me by going from the empirical to the theoretical using a lightbulb, a battery, wires, and relays (which he introduces when he talks about the telegraph as a way to amplify a signal).
Another concept is the relationship between current, voltage, and resistance. For example, I always failed to understand why longer wires mean more resistance while thicker wires mean less resistance.
945 comments
[ 2.7 ms ] story [ 547 ms ] threadI'm not sure if it was years, but it wasn't immediate. I just didn't understand why dependency injection was good at first, and not just someone's weird personal code style choice.
I thought it was just people being "Enterprisey" which I'd encountered many times over the years.
Once I committed to unit testing, I realized how necessary it is.
Unfortunately I still encounter customers who haven't bought into it and as a result have untestable code. It's so hard to go back and retrofit testing.
The term is unfamiliar to me -- is it related to "fault injection"?
it makes the code cleaner and testable.
A. Also depended upon by other, coequal unrelated classes, possibly maintained by others, OR
B. Depended upon only by a single class (of higher functionality)
Situation A is sometimes called a portability interface; B might be called an internal structuring interface.
The difference has crucial implications for social power relationships between the human developers and users involved.
But this makes testing A in isolation difficult. When testing A, you want to mock out B with an instance the test can manipulate.
So we want A to not create B, instead we want B to be "injected" into A. The general strategy of having B passed into A is called dependcy injection.
This way, your code isn't bound to a specific implementation.
Some DI frameworks even go so far and define all resources in a config file. This way you can switch out the implementation without a recompilation.
https://hasura.io/blog/build-fullstack-apps-nestjs-hasura-gr...
Dependency Injection solves the problem of when you want to create something, but THAT something also needs OTHER somethings, and so on.
In this example, think about a car.
A car might have many separate parts it needs:
We can manually construct a car, like: But this is tedious and fragile, and it makes it hard to be modular.With dependency injection, it allows you to register a sort of "automatic" system for constructing an instance of "new Foo()", that continues down the chain and fetches each piece.
And then "class Car" would have an "@Inject" in it's "constructor", and so on down the chain.When you write tests, you can swap out which instance of the "@Injected" class is provided (the "Dependency") much easier.
The alternative to dependency injection is for functions to instantiate dependencies internally rather than having them be passed in from the calling context.
If you've ever written a constructor for a class that has arguments (within the constructor signature) that are used by the instance of the class when instantiated then you have done dependency injection, or put more simply 'passing stuff in' which was eloquently stated in another comment on this thread.
In any case, DI is not at all a new trendy term. Inversion of Control dates back to the gang of 4 patterns book from the '90s. Yes, constructor parameters are one way to implement DI, but not the only one. I'm ambivalent on the whole pattern movement, but they are a great educational tool for novice programmers, and it is good to have some standard terminology for core patterns.
To put it another way, constructor based DI is not simply the use of constructor parameters, it is understanding the OO design principle that side-effecting code should be isolated into objects, rather than just dumping a bunch of DB queries into your functions, like we did back in the stone age.
Todays http servers may have any number of request altering/enhancing "middleware" calls between the incoming request and the actual business logic/function.
How do you ensure that your api works as designed if you only test (pure) business functions? Or do you re-create the middleware chain of functions manually for you test?
You don't need to test the call to /api/foo, you only need to test the call to fooApi(). It doesn't/shouldn't require a http server to do that. Just call the function directly.
If you want to test that /api/foo exists, that is essentially a different test and only requires a mock version of fooApi(), because you've already tested fooApi() separately above.
The benefit of this approach is that your tests run a lot faster (and easier) not having to spin up an entire http server, just to test the function.
As for the middleware... that is also tested separately from the business logic. You don't want to tie your business logic to the middleware, now do you? That creates a whole dependency chain that is even harder to test.
See also: Frontend development that requires running the entire stack in order to test it.
For example, the business logic is what talks to the database. This way, I can test the controller separately from the business logic. Often, I don't even bother testing the controller, since it is usually just a single line call to the business logic.
Anyone who writes a lot of tests realizes very quickly that in order to write testable code, you have to separate out the layers and compartmentalize code effectively in order to allow it to be easily tested. Tracking dependencies is critical to good testing (which is where this whole DI conversation got started).
If you aren't writing code like this, then you're just making testing harder on yourself... and then we end up with tons of code which can never be modified because the dependencies between layers are all too complicated and intertwined. Don't do that.
At this point in my 27+ year career, I don't see any reason to not do things correctly. The patterns are all instinctual and no need to try inventing something new, I don't even think about it any more, I just do it from the start.
As for unit tests... I mostly add them to projects with something egregious happens or a very hard bug to spot can occur - just to prevent anyone else from foot gunning themselves (here be dragons or whatever).
https://github.com/gaffo/CSharpHotChocolateZeroQLIntegration...
Still playing around with the right level for this but this is currently nice as it gives me compiled type checking and refactoring. This is an example/extraction from another project which uses react as the client. Wasn't big on cross language api level tests yet for speed of development, as that's a tradeoff. Redundancy vs even more framework.
When I code review, I try to make sure I call out "fake tests".
It's relatively uncommon for handler/controller code to have logic worth testing, most of the time it's just maintaining the separation of layers and concerns by wrapping gateway/repository calls. All there is to assert about it is that "it calls this function in the next layer."
Every once in a while there's nontrivial functionality to test in the middle, and unit tests can often be a good fit for that, but in my experience it's more the exception than the rule.
One of the only legit use cases for mocks that I have personally come across is validating things like a sequence of API calls to an external service, or queries to a database where there is a check that certain efficiencies are guaranteed, e.g. verify that an N+1 select problem doesn’t creep in, or knowing that a app-level caching layer will prevent redundant API calls.
I think it’s reasonable to disavow expecting single unit tests for nearly every method on every class with mock/boilerplate/copy-paste hell. However, I would still expect “local integration” unit tests that exercise broader chunks of code and keep code coverage up.
So it should be “I don’t need to write a new unit test for this because an existing unit test calls the method that calls this method without it being mocked and you can see it’s covered in the code coverage.”
Or do you mean specifically "expecting" interactions with those mocks? Because I agree that's usually not that valuable.
Ideally, service/library owners would write and maintain the fake to ensure that it stays in sync as changes are made to the actual service.
But it isn't quite as smelly when I see a mock (or "stub" more typically) used as an expedient way to create a fake to pass in as a dependency.
Like you said, it is asserting on the interactions with a mock that is what primarily smells bad to me. I very rarely (honestly I think maybe never) see this done in a way that isn't just rewriting the implementation of the method as expectations in the test.
Over time I have favored very basic unit tests and leaning in more on automated integration and regression tests. I know the theory of unit tests catching things earlier, I just don’t think it matters in practice.
Of course it's not necessarily a full replacement, but it's definitely better and more time efficient than bad tests.
I'd actually say: Not in the slightest. A type system just rules out illegal input values[0] but it won't ensure that your business logic is correct.
And even that[0] is not entirely correct because, most of the time, a type system just rules out some illegal values but not all of them, because it cannot represent all possible constraints. Gary Bernhardt discussed this whole type checking vs. tests debate at length here: https://www.destroyallsoftware.com/talks/ideology
In many cases mocks are now over used where previously they were important in say 2008. Especially now with languages that support functions as objects, better generics, and other features which weren't common a while back. Likewise frameworks are and languages are generally way more testable now which means you're doing less backflips like static injecting wrappers for DateTime.now into libraries to make tests work. This further allows more contract and less implementation specific testing.
As with most things there is a lot of nuance/art to doing it well and smoothly
When programmers really embrace dependency injection like the parent comment, the implementation largely is the inputs, and your code expects them all to be implemented correctly (or mocked correctly by test code). I completely agree that mocks are overused, and their importance in 2008 were in my view a direct result of the popularity of dependency injection patterns.
Following that logic, the best way to remove mocks from your tests is to minimize dependency injection, relegating it all to a single place in the code wherever possible, and implementing all other domain logic as pure functions of input to output. How to test that code which touches other systems? Integration tests (or multi-system tests or whatever you like to call them).
In 2008, I actually found code often got more testatable when it was dependency injected. I spent a month ripping singletons out of a gui application so we could make it into a web service, that would have been a lot easier with a DI model. The system was nigh-on untestable until we got rid of those singletons.
I link it in another comment but https://github.com/gaffo/CSharpHotChocolateZeroQLIntegration... is how I do things these days, api integration test, and more focused unit tests where you don't understand the library well yet, there's lots of tricky edge cases, or error conditions such as setup that are harder to integration test. I'm still feeling it out.
(Which IIRC is what I changed it to)
Thinking about the original TDD approach -- red, green, repeat maybe it's not that bad? I prefer your approach, where you actually verify the state change. But in the absence of that, I wouldn't mind the "call the mock" approach. At least it does change some of the contract?
I suppose having lots of mocks is a smell after all..
However you structure it, there will always be "glue code" that ties the nice inmutable code with the outside-interacting bits, and if you want to unit test those, dependency injection (with functions or state, not classes or instances) is still the way to go.
Using a totally non-OOP functional style, you can either instantiate state within a function or pass it in from the calling context, which is the same trade-off that dependency injection targets.
The abstract concept of OOP (messages between complex objects, as defined by Alan Kay) is an attempt at mimicking biological systems. Most modern languages implement data abstraction, but call it OOP, where they encapsulate some functionality with the data it operates on. Really helped with varying data formats in the AirForce in the 60s, apparently. There isn't anything wrong with this abstract concept either - it's a way of structuring a solution, with trade-offs.
Support for unit testing and mocking has little to do with OOP, and everything to do with the underling platform. Both C++ and Java, for example, do not have a special runtime mode where arbitrary replacement of code or data could occur. This is necessary for mocking functionality that is considered implementation detail and hidden by design. The hidden part is great for production code, not great for testing.
For example, if an object in java has a field like 'private final HttpClient client = new CurlBasedHttpClient();' this code is essentially untestable because there is no way in Java to tell the JVM "during testing, when this class instantiates an HttpClient, use my MockHttpClient".
Kotlin fixed some of that with MockK, which can mock the constructor of a Kotlin object, and you can return your mock implementation when the constructor is invoked.
Clearly, it's a platform issue. There could be a world where you could replace any object in the stdlib or any method or field with a mock version. JavaScript is much more flexible in that regard, which is why unit testing js code is much easier.
The root of it all stems from the fact that unit tests need to change some implementation details of the world around the object, but production code should not be able to, in order to get all the benefits of encapsulation.
If you get rid of modern OOP, you are swinging the pendulum in the opposite direction, where your tests are easy to write on any platform, because everything is open and easily accessible, but your code will suffer from issues that creep up when structures are open and easily accessible, such as increased coupling and reduced cohesion.
I stand by my statement that OOP is totally unnecessary.
Edit: This is more blunt than I intended it to be. For what it's worth, I happen to agree with you in principle, but I also think you're taking the roof off the car here and boldly claiming that the experience is so much better in the summer. What about winter? What about when it rains? What are the trade-offs? Not mentioning the downsides means that you either haven't found them, haven't thought about them or are intentionally omitting them from the discussion.
To dismiss the whole of OOD/OOP so cavalierly just goes to show they don't know what they are talking about.
Much of the success of Modern Software is directly due to the wholesale adoption of OOD/OOP in the last few decades.
Separation of Concerns, Modularization, Reusability, Type Hierarchies, Type Composition, Interface contract-based programming, Frameworks etc. were all made mainstream by OOD/OOP. These are things taken for granted by programmers today. As somebody who has been doing OOD/OOP since the early nineties i can tell you it was the single biggest reason for the explosion of Software in the past few decades.
As a concrete example, early in my career i had programmed in C using the Windows API; both 16-bit and Win32 (Thank you Charles Petzold). It was difficult, tedious and a lot of work. And then Microsoft introduced MFC (Microsoft Foundation Classes) Framework with Visual C++ IDE. With a few clicks of the wizard, i had a complete skeleton application with a lot of hard work already done for you. That was a revelation for me on the power of OOD/OOP. Things i had slaved over in Win32 was now at the fingertips of every noob who could type. The same revelation happened (but not to the same extent) when i moved from Xlib to Motif on Unix platforms.
I had pointed you to Bertrand Meyer's book OOSC2 (in my other comment) as the book to read to understand OOD/OOP. Another great book to study is Barbara Liskov and John Guttag's Program Development in Java: Abstraction, Specification, and Object-Oriented Design.
I was formally trained and cut my teeth in OOP code bases and my latest company we are very light on classes. 99% is plain objects and modules that operate on them. Everything is very straightforward and logical. In my side projects I’ve stopped using classes as well and it’s so much cleaner.
This is opinion and preference. If I hired a guy who wanted to litter the code base with AbstractUserBeanFactoryFactories I’d have to let them go because it’s a situation I don’t want anymore.
This is putting the Cart before the Horse. Computers, Internet etc. can't do anything without the Software to drive them. That software is written in some Language/Tool using some Paradigms and Software Engineering principles. The ease of use, ease of structuring, ease of understanding etc. of these are what drives Creation, Adoption and Expansion of Computing and Devices.
>I was formally trained and cut my teeth in OOP code bases and my latest company we are very light on classes. 99% is plain objects and modules that operate on them. Everything is very straightforward and logical. In my side projects I’ve stopped using classes as well and it’s so much cleaner.
If you think merely using a syntactical structure like "class" (and Design Patterns) is what makes code OOP, then you don't understand OOP. You can do various degrees of OOP without language syntactical support. This is why i listed the principles and not some syntactic sugar in my previous comment. It is a way of thinking and Software Engineering which has given the most "bang-for-buck" so far in the Industry.
>This is opinion and preference. If I hired a guy who wanted to litter the code base with AbstractUserBeanFactoryFactories I’d have to let them go because it’s a situation I don’t want anymore.
Opinion and Preferences must be based on facts else it is only as good as "Flat Earther" category and nothing more can be discussed.
Class s: fun a(self)... fun b(self)...
The problem is mutability not how state is bound to a function.
Though it’s not always practical, like when needing to push an element to an array for making updated state. It is nevertheless possible to shave of pure parts considerably making mutability easier to maintain.
Similar, OOP is an obfuscated way to run a function with a context. The first time you separate the data in the context from an object, it’ll be hard to get it right and make it easier than to just use Objects and Methods. But once you’ve done it two or three times, it’s as easy as breathing.
You can optimize loading the context to be better than copying a bunch of unaligned data in lots of ways, but polymorphism is a common way to get there.
I am a Scala programmer, and our code mixes OO and FP. Almost all of our classes are completely immutable.
In the end, you will always need to encapsulate data and functions in some manner. The FP approach involves module systems, but as I understand it, objects in Scala actually provide a better module system than found in pure FP languages.
The few times I had to use Java afterwards I felt the same - all OOP features were unnecessary or at least didn't feel like the most straightforward approach. Nowadays I never use classes in Python, JS etc., it's just not needed - and in the case of Python it makes JSON insanely cumbersome.
I always hated testing and I still do, but every time I commit to doing it right I catch so many errors before QA.
But that's a long way from glorious full DI containers where you never call 'new' in your code anywhere and all object creation can be dictated by config. I suspect that must be only the kind of thing that people who maintain 1,000,000 line codebases that are at the center of massive bureaucracies.
Just vanilla C++ classes, and virtual interfaces if we need to mock things for unit tests.
No automatic wiring of the hierarchy.
Although you might say that microservices are like a distributed DI framework that would let you rewrite or mock components provided that the rewrite/mock adheres to the API framework (curiously, I've actually seen that used in tests with a quick and dirty in-memory sequential unauthenticated server used for testing clients where the server passed the same API test suite as the real server).
The idea that I take advantage of good abstractions and I send those objects into my classes that need to perform actions via those abstractions made a lot of sense. Helps enable good polymorphism, as well as unit testing and other things.
I don't think I'm doing it justice, but the idea took a good while to understand there reasons behind it. Some books that helped me grok the idea were
- Patterns of Enterprise Application Architecture - Clean Architecture - Architecture Patterns with Python
along with running into problems that could be easily solved with a decent abstraction at work and learning to apply it directly.
Almost no one I encountered bothered to actually explain anything. They simply regurgitated things and I guess expected me to somehow intuitively understand something or other.
>The best math textbook (Theory of Algebra) I ever read had little sections about the person who revealed a particular subject, why they were studying it, and how the subject is used.
I've found the best type of books provide motivation for concepts, how they have evolved, etc.
Take Computer Science for example, many of its concepts were area of research for decades but from a student's perspective it seems these concepts were always here instead of being constantly refined until the states they're now in.
- Learn the definition - Learn the motivations and history - Peruse a few examples - Try to map the above to a brief synopsis that explains the concept in intuitive terms that relate to your own life. Rely on pictures.
Finally, I find it helpful sometimes to try and "deduce" identities from "first principles". e.g. assume I didn't know that n^0 = 1. How might I reach that conclusion? If I have an understanding of what exponentiation means I should be able to come up with a few different propositions (these could even be relatively informal) that make such a conclusion make sense.
My childhood was rife with mathematics teachers that focused more on rote memorization of identities instead of careful explanation of definitions and development of "intuition". There's pretty much no better way to ensure you'll produce students that dislike and suck at math for the rest of their lives than proceeding by mind-numbing rote memorization.
>There's pretty much no better way to ensure you'll produce students that dislike and suck at math for the rest of their lives than proceeding by mind-numbing rote memorization.
I couldn't agree more.
https://www.punkademic.com/course/music-theory-comprehensive...
Music theory is not inherently complex, but the notation adds incidental complexity -- it's sort of like the QWERTY keyboard; once you're stuck on a suboptimal way of doing things it's hard to move off.
My single largest goal when I'm teaching, is to find an appropriate analogy to a concept that my student already grasps, and bridge it to the new concept. Some fields make this super easy -- MechE and electronics, for instance, if you understand one, you're well on your way to understanding the other -- and some make it super hard.
Music theory is descriptive, not prescriptive. Is it any surprise that something we had to invent a whole new symbolic notation for is difficult to connect to concepts we can describe in natural language?
If you want to go really deep into the philosophy of music, to understand it from "first principles" so to speak, I highly recommend Leonard Bernstein's lecture series "The Unanswered Question" - https://en.wikipedia.org/wiki/The_Unanswered_Question_(lectu... (available on YouTube).
To paraphrase Bernstein's comment from his book "The Joy of Music": we need to stop comparing Beethoven to grassy fields and mountain streams. A "major seventh" or a "plagal cadance" are themselves the description of those qualities. By all means use music as metaphor, but when you're trying to describe it you're going to be using terms specific to its domain.
I was probably in my late 30s or early 40s before I really grokked why that tended to be true. (I could blindly accept and grind through the equations to get the answers in college, but it was decades later that I developed a feel for why.)
So many useful groundings in various super important comp sci concepts.
https://intercoolerjs.org/2016/01/18/rescuing-rest.html
much later:
https://htmx.org/essays/hateoas/
I don't think I really understood that completely until I started TA-ing.
Good problem sets that aid studets' intuition aren't easy to come by, oftentimes they're either too easy or too hard.
The caveman pressing the alarm button is something I think of a lot.
I presume you already know of this book: The Body Keeps the Score: Brain, Mind, and Body in the Healing of Trauma by Bessel van der Kolk.
[0] https://betterexplained.com/articles/colorized-math-equation...
3Blue1Brown -- But what is the Fourier Transform? A visual introduction.
https://www.youtube.com/watch?v=spUNpyF58BY
Reducible - FFTs the most ingenious algorithm ever https://youtu.be/h7apO7q16V0 Veritasium - The Most Important Algorithm of All Time https://youtu.be/nmgFG7PUHfo
Entropy in classical thermodynamics is presented in a mysterious way that leads to confusion.
Entropy in statistical thermodynamics, however, is logical. Once one understands basic statistical thermodynamics, entropy isn't mysterious.
The book in my statistical thermodynamics class was An Introduction to Thermal Physics by Daniel Schroeder, which is an excellent book that I've referred to many times since.
To me, the issue with entropy is that it's initially presented without clear justification, so people don't know why it's important. Statistical mechanics made it clear to me that the state with the most entropy is the most likely to occur in equilibrium. (Statements about entropy representing "disorder" and whatnot in my opinion are handwavy, often lead to confusion, and should be avoided.)
Edit: but that was only after I had grokked Shannon's paper on information theory, which I felt was pretty intuitive.
The model itself is easy enough to grasp. But concretely understanding what it implies about how I should be studying took much, much longer.
The way our brains have evolved to build up a functional language model is by observing lots and lots (and lots) of examples of the language being used for communication. Which implies that, even from the very beginning, graded readers, level-appropriate dialogues, etc. should be the foundation of a language study program and not, as most language instruction courses and apps make it, just a little bit of icing on top.
The primacy of input is also kind of a big deal, and, at least for me, it took a long time before I was willing to let go of forced production exercises such as "translate this sentence into your target language". Perhaps in part because they're so endemic to language learning resources. You can't abandon them without also abandoning Duolingo and most formal classroom programs. But the problem with these kind of practice exercises is, we now know that it's normal for there to be a long delay between when someone can comprehend a grammatical structure, and when they can use it in a natural setting. (Anyone with kids over a certain age should be familiar with the phenomenon.) Forced production relies on - and reinforces - that aforementioned misplaced encoding, and there's a mountain of research demonstrating that skill in performing those sorts of exercises simply doesn't correlate with the development of communicative fluency.
Tangentially, the transformer architecture that's taken natural language processing by storm has some interesting similarities to the leading model among SLA researchers for how language is represented in the human brain. Which isn't the monitor model itself, but might hint at a mechanism for a few parts of the model. Acquisition order, for example.
What I like to do is spend at least an hour a day reading, listening to podcasts and audiobooks, or watching videos. A good day for me is a day when 100% of my media consumption for entertainment purposes is happening in my target language.
And that really is it.
I don't really bother soliciting explicit feedback. I suspect that it's potentially harmful because it can trigger the affective monitor. I've also encountered some SLA researchers saying the research indicates that it's not actually helpful. I'm becoming increasingly enamored of Bill VanPatten's conceit that, in a language learning context, there's no such thing as errors, there are only differences between the learner's interlanguage and their target language. Which is something that should be embraced as a natural and essential part of the process rather than a problem that needs explicit correction.
So what I do instead is just pay attention to whether successful communication has happened. When getting input, that means I'm focused on whether I understood the content or not. I want it to be a little bit difficult, enough so that I'm not getting bored, but not so difficult that I feel I'm really straining to comprehend. (There's nothing scientific to that, it's just personal taste.) When I'm having a conversation with somebody, I'm just interested in whether or not I am having a successful interaction. In a sense, what I'm trying to do is set up a feedback loop that optimizes for pure enjoyment, which, for me, seems to be a very good proxy for learning effectiveness.
To that end, I don't really intend to shit on Duolingo and practice exercises and whatnot. A lot of people enjoy those approaches to language learning, and the single most important thing is that you enjoy what you're doing.
https://en.m.wikipedia.org/wiki/Lie_group
This paper was the catalyst to me finally grasping some of the details: https://arxiv.org/abs/1812.01537
always seemed like a shitty expensive database for 7+ years
therefore it’s safer to build then on twitter, facebook, apple, etc.
the entire ecosystem may be a fraud, but if it is not then it’s incredibly enduring. i have more faith that i can get what the balance of an account is in 10 years from ethereum than i do from my banks api staying stable or open.
Predicate Calculus is used to show that the path followed by a Process through a Cartesian Product space (created from all the memory variables in a Program) is the one you had in mind w.r.t. its Specifications. Suddenly you start to understand basic Set Theory, Types, Relations (Functions) and Logic.
Over the past few years, I've been teaching myself how to write better. I'm not talking about elementary syntax or grammar. I'm not talking about writing the traditional, American English five paragraph essay. I'm talking about writing longer pieces of prose, articles or blog posts or short chapters with word counts ranging anywhere between 1500-3000 words. On this journey of improving the craft, I realized that one of my biggest struggles was writing cohesively. Although I've been able to get lots of words on (digital) paper, eventually I'd get lost in my own web of thoughts, the article itself totally incoherent, no structure, no organization.
Constructing outlines and reverse outlines[0] has helped me tremendously. It's not easy ... but the concept itself is finally — years later — starting to click.
[0] - https://explorationsofstyle.com/2011/02/09/reverse-outlines/
It sounds dumb, but this year it clicked for me how big of a difference a poorly written text compares to a well written text.
Hope your training pays off, itsmemattchung!
I got Joseph M. William's "Style: Toward Clarity and Grace" recommended [1] so you might be interested in it. I read the introduction (I'm planning to read it this year) and with the few examples the author presents it sells the idea that prose doesn't need to be utterly complex to communicate ideas and concepts succinctly and clearly.
[1]: https://news.ycombinator.com/item?id=33601492
My top 3: 1/ Edit ruthlessly. Every single word is reduced to its simplest form and pulls its weight--it has a damn good reason for being there. 2/ Aspire to write at a third-grade reading level. Readers prefer simple writing even when reading deeply technical content. 3/ Start your most important conclusions up front, not at the end. You're not writing The Sixth Sense. Do your reader a favor and tell them the big reveal first. You can then follow through and persuade the reader why your conclusions are right.
It's just so much experience to avoid those mistakes.
Something I realised much too late was how delaying the move to the keyboard was a useful strategy. Now I mostly start with pen and paper, sometimes with a mind map if I really need to organise my thoughts, and only hit the PC once I have a pretty firm idea of what I'm going to say. I've even done first drafts in longhand, which feels like double handling at first, but there's something about that added filter of transposing from paper to computer that helps you reassess objectively what it is that you're writing.
Also, obligatory RiffTrax on outlines: https://youtu.be/yfcyVtD8-Dk
Out of curiosity, in the skit, do you know which book the actor is reading? In the skit, at the top of the page, the book is titled: "Making outlines and summaries"[0].
[0] Fast forwarded to specific time: https://youtu.be/yfcyVtD8-Dk?t=129
A couple seconds before yours, he has an index card with the title “Directing Learning 371.3”
A quick search yields the title: https://openlibrary.org/works/OL7389387W/Directing_learning
But I was unable to find a physical or digital copy available. Good luck!
https://www.abebooks.com/servlet/BookDetailsPL?bi=2072352131...
This is a great way to refine your ideas before you write and makes it easier to develop the outline as an assembly of different notes that you already have.
An Executable Strategy for Writing: https://notes.andymatuschak.org/z3PBVkZ2SvsAgFXkjHsycBeyS6Cw...
The main insights for me were: - Using notes as a way to organize one's writing (by assembling ideas together into an outline, then filling out the details) to avoid writer's block. - Creating "logs" around concepts that extract useful ideas from ephemeral observations and distill concrete insights over time. - Using an "inbox" of new ideas as a way to focus attention and perform spaced repetition of concepts. - Organizing notes via tags, backlinks, and associations/outlines rather than as a hierarchy. - Incrementally iterating on atomic concept notes to form larger chunks in memory which allows thinking about more complex ideas and recognizing patterns.
The wikipedia page for it explains it well.
What manual process does ChatGPT speed up?
When you simply Google something, you're presented with blogs, articles, stackoverflow pages, github repositories, documentation, ... you're still left with the manual process of parsing all of the results, e.g. turning what you've read into runnable code, summarising and taking notes in a format that is easy for you to follow.
Furthermore ChatGPT allows you to have a dialog about the results. Maybe you have two equally interesting results and don't know which one to go with? Usually you'd have to do "sub-googling" in cases like this and once again parse, aggregate and format those results. With ChatGPT you can basically just ask it to expand on the previous results and help you figure out what to do.
Save humans time.
Save humans time.
When I got out of my middle class bubble, made friends with people working multiple jobs and struggling to make ends meet, and experienced a period of financial instability; I began to realize that something wasn't working in our current system.
Then I started struggling with burnout and other issues and found that corporations were happy to just replace me. I also found that management wanted programmers to be replaceable cogs instead of professionals. At that point I started to suspect that the idea of a dignified professional lifestyle may not be true.
I observed that technology and products were getting worse over time. For example, Google search has become mostly useless and it's hard to find products that are made to be repaired. I concluded that the invisible hand and/or the price theory of value were not true.
Then I saw Republicans gain power and run up the national debt. I also observed that when wages actually started increasing the economy fell apart and the Fed started taking steps to prevent wage increases. I concluded that "free market" rhetoric was a lie.
At that point I looked for alternatives and found socialism. In particular the "social democracy" strains of socialism as opposed to those advocating central planning or anarchist organization.
Yes; Most people get hung up on terminology and/or specific interpretations but i am convinced this is the natural order of things for the Human species. The balance without going to extremes is what is important.
Because terminology matters, and some terms are quite misleading. What some people tend to miss about the "Socialism with Scandinavian Characteristics" that folks claim to like these days is that Scandinavian countries are actually near the very top rankings by economic freedom and lack of excess regulatory burden. I.e. they're actually some of the most free market and capitalist, while applying effective redistribution after the fact (leading to moderately high tax rates). So I don't get why people decry capitalism and free enterprise while praising Scandinavia as "successful" socialism? It makes no sense.
Let people go wild and try stuff and do whatever but raise the floor up to the point where people can recover from failure and where the less fortunate are not suffering.
This kind of “social capitalism” could be freer and less regulated than what we have now.
While also somewhat contested in Germany, and not free of (some) valid criticism, I would advocate to try and use the term "Social market economy" [1].
[1] https://en.wikipedia.org/wiki/Social_market_economy
Well, full-blown free-market capitalism would be one alternative to the current US system, albeit probably not the best.
That’s not supposed to happen. Adding a way for people to make income is supposed to incentivize better content and allow people to invest in that content. Instead what you get is a flood of addictive and sensational / tabloid trash.
… or another way of looking at it is that you do get “better” content but better is not defined in a way that truly benefits anyone.
YouTube is the most dramatic example. The quality of the whole platform tanked hard when monetization was added.
After seeing this a few times I have started noticing it everywhere. The profit motive just doesn’t incentivize quality the way we are taught that it should. It can when the incentives align but they often do not.
Another common example is actual reductions in quality to drive more spending like engineered obsolescence or “nerfing” software to drive lock in. The incentive is to produce an inferior product since that is most profitable.
This doesn’t mean I think the answer is a government bureaucracy running everything like a single monopoly. That leads to a whole other set of perverse incentives and an inability to go elsewhere.
What it does is incentivise more content. More is not always better for everyone, and is even less likely to be better for those who were early adopters to the platform - but what it is usually is more popular. It's just democracy in action: the largest numbers decide, and sometimes privileged minorities lose out.
My opinion, however, is that my parents did the right thing to drag me out of such a system and into a capitalistic one. I am watching my peers suffer.
Then a summer went by before the third time I took it.
When I stepped into class that third time, everything clicked and it all felt very obvious to the point where I could anticipate where the lecturer’s equations were headed.
I stopped attending class and still got an A. I even ended up helping classmates in a study group.
I still can’t explain what that brain process was that resulted in the pieces subconsciously lining up over the summer.
[0] https://www.readthesequences.com/An-Alien-God