Live data from Hacker News

Software Engineering principles to make teams better

principles.dev

71–80 of 105 posts

Re: Software Engineering principles to make teams better

#71
It'd be cool if counter-points to a principle could also be documented alongside it. Reasoning that highlights why you may not want to adopt a principle is helpful when considering it.

For example, take "One single source of truth".

>Data should be held in one location, duplicates of that data should be by reference only.

>Why

>Changes to data are always propagated to the rest of the system.

>Mutations to the data need only happen in one place.

>Single source of truth means no data will be out of sync or fail to be updated.

>How

>Only allow data writes to happen in one location. Whether that be a call to a rest API, system call or other write actions.

>Don't allow data to be stored anywhere but the single source of truth.

That won't work in many situations. If you need to support high throughput OLTP use-cases but also want to support advanced filtering/sorting of large datasets, you may need something like a combination of a NoSQL DB with something like ElasticSearch. Eventual consistency is something you accept as a trade-off for enabling higher levels of performance.

Re: Software Engineering principles to make teams better

#72

I think i’ve got a slightly different take - i’m not saying my take is any better though. If we’re talking engineering principles, not team dynamics, then it’s: 1. Use immutability by default, even in languages that make that harder than it should be 2. Understand how liberating idempotency is 3. Divide and conquer, use abstraction to make hard problems manageable 4. Delete code, delete tests, re-write stuff, re-writ…

I agree with everything except for this: > 4. Delete code, delete tests, re-write stuff, re-write it again. Painful? Keep doing this till you get to the other side and feel liberation and empowerment, took me years to get past wincing at the idea of re-writing that thing AGAIN With experience I've realized that rewrites are almost never a good idea[0]. They are time consuming and inevitably introduce new bugs (or rei…

My thinking definitely aligns with yours on this:

> if you're making significant changes to a unit of code anyway, clean it up or rewrite it; otherwise, make the smallest change necessary and leave it alone. If it ain't broke, don't fix it.

Don't be afraid to rewrite something when it needs it, and build knowing it's very possible you'll rewrite later.

If there are good unit tests, and it's a sufficiently small/decoupled piece of code, then rewriting is not so bad. These are all self-reinforcing things: small, decoupled code tends to be easy to rewrite; Testable code tends to be decoupled.

Systems always get more complex over time. The key thing is figuring out when your simple component is starting on the path to getting too complex, and taking the time to rewrite it as early as possible -- maybe it should be two smaller components, or maybe the entire organization of that are needs to be different. If you wait, and just keep adding "small" things, eventually you have a monster that's an order of magnitude more complex to deal with.

The other bit of this is writing code knowing you can (and may likely) rewrite it later. If you try to predict the future complexity early in design, 9 times out of 10 you will get it wrong, and you'll end up in a lose-lose situation: you have a overly-complex component to deal with, and it ends up needing a rewrite later anyway. Rewriting this is even harder because you have to undo the unnecessary complexity. This is also known as YAGNI ("You Aren't Gonna Need It").

Re: Software Engineering principles to make teams better

#74
post #68

Earlier quoted context omitted.

I agree with everything except for this: > 4. Delete code, delete tests, re-write stuff, re-write it again. Painful? Keep doing this till you get to the other side and feel liberation and empowerment, took me years to get past wincing at the idea of re-writing that thing AGAIN With experience I've realized that rewrites are almost never a good idea[0]. They are time consuming and inevitably introduce new bugs (or rei…

> With experience I've realized that rewrites are almost never a good idea [...] If your architecture allows it, it's better to sandbox working legacy code and leave it as-is than constantly rewrite it. What if your architecture is the problem? If you got the domain model wrong and you have deeply-nested complex types used throughout, you will never break free without a clean sheet rewrite. Certainly, you can refacto…

I might, grudgingly, support this kind of rewrite, if it was proposed with a domain model that can already support all existing data. If it's proposed with "a new domain model would be so much nicer! We could do it right!" then hell no.

I'd still prefer to do it incrementally if possible.

Re: Software Engineering principles to make teams better

#75
post #32

Earlier quoted context omitted.

> Use immutability by default, even in languages that make that harder than it should be That and referential transparency are huge wins. It is a shame languages like Python make it such a challenge.

It's easy to do immutability in python, just use NamedTuple for classes and tuple instead of list

Since PEP 591 [1], if using mypy with Python 3.8+ or the typing_extensions module, you can also take advantage of typing.Final, which lets you statically verify something isn't changed. The catch is that it isn't enforced at runtime.

  [1]: https://www.python.org/dev/peps/pep-0591/

Re: Software Engineering principles to make teams better

#76
post #71

It'd be cool if counter-points to a principle could also be documented alongside it. Reasoning that highlights why you may not want to adopt a principle is helpful when considering it. For example, take "One single source of truth". >Data should be held in one location, duplicates of that data should be by reference only. >Why >Changes to data are always propagated to the rest of the system. >Mutations to the data ne…

It's funny you chose that principle in particular because it does have an exception listed:

https://principles.dev/p/one-single-source-of-truth/

> Exceptions > Highly distributed systems - Some systems rely on data consistency to be reached eventually or may never need to have accurate data.

I've written about exceptions here: https://principles.dev/documentation/#exceptions-optional

In general, exceptions should be quite broad and people can add these to the principles if they know of them.

They can also have higher priority "contradictory principles" which override the lower priority principles in certain cases.

Overlapping of principles create complex behavior so it is usually better to have a list of principles in priority order (this will be covered under emergent behavior in "principle-driven engineering") which can override the "single source of truth" principle.

An example might be: Engineers will know they should use single-source of truth, but as performance should be critical (or they have a specific business rule that states something must take less than 5ms) it will override that principle.

Does that answer your question or do you think it needs to be more refined than that?

I wonder if making the principles editable by the team would be a useful feature, so you'd be able to add your own exceptions to them for your particular use case.

Re: Software Engineering principles to make teams better

#77

I once worked at a startup which had put together a binder of documents, declaring the company's vision, values, principles, etc. They strongly suggested new hires go through it at least briefly. I don't think anyone ever did.

Yeah, I know what you mean.

I've a few principles for that: https://principles.dev/p/documentation-should-be-close-to-th... and “They Ain’t Gonna Read It” (not on the website, yet. But it is here: https://blog.nuclino.com/brown-m-ms-or-why-no-one-s-reading-...)

The trouble with the documents you've mentioned is they don't really create capability and it's really the social structure that enforces those values and principles as opposed to the documents.

With engineering it's different because it provides tangible value.

From a team perspective it can help you transfer mental models. Programming is an abstract activity that benefits greatly from those shared models. They build capability, help people learn rapidly, settle disagreements, bring the team together as one and are used in things like code reviews and filtering of technical decisions. People come back to them again and again - it's integrated. Then when a new member of the team comes a long, you're not going back to those discussions again and again.

As an individual. One of the reasons you look back at your principles to remind why you believe something or to be more convincing. They provide value, so they keep being used. It's also part of that persons identity. It defines what they care about and helps them join teams with people who are aligned.

So I agree to an extent - They Ain’t Gonna Read It... Unless it provides value.

Re: Software Engineering principles to make teams better

#78

Earlier quoted context omitted.

This was the first time I've encountered the mention of "referential transparency", so I looked it up and went down a deep rabbit hole. It seems that it's normally used to describe the property of not having side effects, however, I also found this long explanation on Stack Overflow: https://stackoverflow.com/a/9859966/58099 So now I'm more confused than when I initially read your comment. Do you mean "referential tr…

I just mean it in the sense of functions without side effects on data in the program (I’m not fussed about I/O).

In this particular case do you just mean pure functions then?

Re: Software Engineering principles to make teams better

#79

Earlier quoted context omitted.

I just mean it in the sense of functions without side effects on data in the program (I’m not fussed about I/O).

In this particular case do you just mean pure functions then?

Sure. I’ll be honest, the distinctions are challenging to me.

Re: Software Engineering principles to make teams better

#80

I think i’ve got a slightly different take - i’m not saying my take is any better though. If we’re talking engineering principles, not team dynamics, then it’s: 1. Use immutability by default, even in languages that make that harder than it should be 2. Understand how liberating idempotency is 3. Divide and conquer, use abstraction to make hard problems manageable 4. Delete code, delete tests, re-write stuff, re-writ…

> 1. Use immutability by default, even in languages that make that harder than it should be

What I've come to realize is that whenever people talk about wanting immutability, they really want value semantics. Value semantics can be achieved without immutability - the best example is Swift's structs. They can be both mutable or immutable, but they can never be shared, i.e. there can never be more than one reference to a single struct value. This means that modifying the value has no effect on other references, because there can be no other references.

This makes whether or not the value is immutable irrelevant, or at least not necessary. You get the same benefits - you can reason about your code locally and not worry about your changes modifying unknown parts of the program. Local reasoning is the end goal, and value semantics is the mechanism of getting to that goal. Immutability is only one way of getting value semantics.

Post reply on HN