Live data from Hacker News

The Design of Software is a Thing Apart

pathsensitive.com

101–110 of 124 posts

Re: The Design of Software is a Thing Apart

#101
post #39

Earlier quoted context omitted.

> Some might claim unit tests will solve this Yes. Tests will solve this. Your point is perfect for tests. If another experienced coder cannot comprehend from the tests why something is wrong, then improve the tests. Use any mix of literate programming, semantic names, domain driven design, test doubles, custom matchers, dependency injections, and the like. If you can point to a specific example of your statement, i.…

> a complex method that you feel can be explained in documentation yet not in tests, I'm happy to take a crack at writing the tests. // This implementation is unnatural but it is needed in order to mitigate a hardware bug on TI Sitara AM437x, see http://some.url (that's an obvious one; but there are plenty of other cases where documentation is easier than a test)

Turns out this is a great example of why tests are better than documentation.

One way to implement this is by using two methods: one normal and one with the hardware mitigation code, with a dispatch that chooses between them.

This separation of concerns ensures that your normal code runs normally on normal hardware, and your specialized code runs in a specialized way on the buggy hardware.

This separation also makes it much clearer/easier to end-of-life the mitigation code when it's time.

Re: The Design of Software is a Thing Apart

#102
post #2

the information of a program’s design is largely not present in its code And that's the problem. We need ways to make those higher level designs (~architecture) code.

This is the problem that I've run into trying to use formal methods. I love them, I can express some things very concisely and even clearly. But there's no direct connection to the code and so keeping things synchronized (like keeping comments synchronized with code) is nigh impossible. We need the details of these higher level models encoded in the language in a way that forces us to keep them synced. Type driven de…

Especially in the functional space there are some good ways to do DDD, although I don't see why we limit this to functional languages.

https://fsharpforfunandprofit.com/series/designing-with-type...

Re: The Design of Software is a Thing Apart

#103
post #69

Earlier quoted context omitted.

This is the problem that I've run into trying to use formal methods. I love them, I can express some things very concisely and even clearly. But there's no direct connection to the code and so keeping things synchronized (like keeping comments synchronized with code) is nigh impossible. We need the details of these higher level models encoded in the language in a way that forces us to keep them synced. Type driven de…

Gilad Bracha wandered off to work on progressively typed languages after he’d had enough of trying to fix Java’s type system. I think if it took something like JSdoc and have it more teeth you could do something like this in just about any of the dynamically typed languages.

Well, he also "wandered in" from doing optionally statically typed languages...see Strongtalk and Newspeak. :-)

Re: The Design of Software is a Thing Apart

#104
post #2

the information of a program’s design is largely not present in its code And that's the problem. We need ways to make those higher level designs (~architecture) code.

This is the problem that I've run into trying to use formal methods. I love them, I can express some things very concisely and even clearly. But there's no direct connection to the code and so keeping things synchronized (like keeping comments synchronized with code) is nigh impossible. We need the details of these higher level models encoded in the language in a way that forces us to keep them synced. Type driven de…

>use formal methods.

My admittedly very brief experience with formal methods was that they were actually less close to the "design" of the software than the code. So not sure that's a direction that will get us anywhere we need to go.

>in a way that forces us to keep them synced.

Why "synced"? Wouldn't it be better if those higher level designs were actually coded up and simply part of the implementation, but at a level of abstraction that is appropriate to the design.

We used to increase our level of abstraction, but now we appear to have been stuck for the last 30-40 years or so. At least I don't see anything that's as much of a difference to, let's say Smalltalk as Smalltalk is to assembly language.

Re: The Design of Software is a Thing Apart

#105
post #91
post #29

Earlier quoted context omitted.

See my recent comment: > We need model based editing environments that will allow us to have a much richer set of software building blocks. https://news.ycombinator.com/item?id=16117668

I've had similar thoughts, notably as a way to side-stepping the composability limits of current parsing theory. But these limitation are increasingly worked around... And looking at rust, I can start to imagine a future where macros are powerful enough to support a lot of declarative coding. When coding javascript today I write code like: // can be imported, and api.router() mounted in express let api = new API(...)…

Nice.

But also a workaround, right? Because it's not actually declarative, it's APIs that are made to look declarative-ish.

So there's several layers of mismatch, for example most of the active ingredients being strings, meaning you're coding mostly in the string-language embedded into JS.

We do that a lot.

Probably time to start looking at our workarounds (and Macros are another workaround) and figure out what we are actually trying to do.

Re: The Design of Software is a Thing Apart

#106
post #54

Earlier quoted context omitted.

Here I'd distinguish between system/integration and unit tests. Unit tests as a whole tend to amount to a mirror of the code base. If a given function f returns '17' and a test validates that fact, all we've done is double check our work -- which has some value, but doesn't protect against the case in which f is _supposed_ to return 18 and both the code and the test are wrong. OTOH, system tests provide a realm where…

IMO tests should never do this unless the function's role is obvious. This prevents internal restructuring (Which is bad!). What you should instead prefer is end-to-end testing. So for a lexer, you'd create a dummy program with the output of each token on a newline, and then test that the tokenizer's output matches what you expect from the input. But you shouldn't test whether the functions themselves are correct. Th…

Completely disagree here. If you test this way you'll be sure to have a correct implementation for this dummy program. Further, if the test fails you now have to try and figure out what component caused the failure.

A unit test should test a specific unit; commonly a class. You should have unit tests for the interface of that unit (never private or even protected methods). This absolutely does not prevent internal restructuring but it drive you toward seeing your classes as individual service providers with an interface.

Re: The Design of Software is a Thing Apart

#107
post #94

Earlier quoted context omitted.

I deliberately used the character literal ‘A’ and not any of your UTF8 strings. I think you are mistaken to confuse a character with your strings. Is this wrong?

You can have a unicode character literal -- and depending on the language there's no distinction between character and string (at the type level), a character is just a string of length 1.

I was assuming C, where there is a difference.

int main() { printf( "%d %d\n", 'A', "A" ); return 0; }

produces: 65 197730221

since the value of string "A" is its base address.

Re: The Design of Software is a Thing Apart

#108
post #96

Earlier quoted context omitted.

This doesn't satisfy the time constraint though. return 1.0f / sqrt(x) Passes a property based test but now your game doesn't actually run because it's much too slow of an operation on hardware at that time. You can also test execution time too, but that's finicky and doesn't help explain how to fix it if you break that test (if there's no accompanying documentation).

But at this point all you're saying is "I can't think of a way of testing performance".

No I'm saying a test for performance doesn't accurately describe the reasoning behind it without accompanying documentation.

Speed is the entire purpose of this method, not the numerical accuracy.

Re: The Design of Software is a Thing Apart

#109

Earlier quoted context omitted.

Old and somewhat contrived example, but the first thing to pop into my head is the famous fast inverse square root function. float FastInvSqrt(float x) { float xhalf = 0.5f * x; int i = *(int*)&x; // evil floating point bit level hacking i = 0x5f3759df - (i >> 1); // what the fuck? x = *(float*)&i; x = x*(1.5f-(xhalf*x*x)); return x; } I can't think of a way to write a test that sufficiently explains "gets within a c…

Write a property based test, ie generate a bunch of random inputs, then assert that all of them are within some (loose) margin of error.

> Write a property based test, ie generate a bunch of random inputs, then assert that all of them are within some (loose) margin of error.

So someone comes along later, look at your test, and wonders: why did you go through all that trouble? You can definitely write tests for a lot of that stuff, but they still don't fluently communicate the why of your choices.

Re: The Design of Software is a Thing Apart

#110
post #84

Earlier quoted context omitted.

Old and somewhat contrived example, but the first thing to pop into my head is the famous fast inverse square root function. float FastInvSqrt(float x) { float xhalf = 0.5f * x; int i = *(int*)&x; // evil floating point bit level hacking i = 0x5f3759df - (i >> 1); // what the fuck? x = *(float*)&i; x = x*(1.5f-(xhalf*x*x)); return x; } I can't think of a way to write a test that sufficiently explains "gets within a c…

For example, here's one way to write a test that sufficiently explains "gets within a certain error margin of the correct answer yet is much much faster than the naive way". Using Ruby and its built-in minitest gem: 1. Write a test that does minitest assert_in_epsilon(x,y,e) 2. Write a minitest benchmark test that compares the speed of the fast function with the speed of the naive function. Notice the big advantage f…

> Exactly. We have the code file, but not any documentation separate from the code, such as notes, plans, attempts, reasoning, etc.

I agree with you that it can be tested. But it doesn't explain anything about why it works, or what methods the author tried that didn't work as well. If you ever had to make it faster, or make it work better on different hardware, you'd be starting from scratch again.

Post reply on HN