6 ms·
If it's not too much trouble, could you create a minimal demonstration of a simple piece of code, structured for various goals - easy to extend, easy to debug e
by UweSchmidt 3y ago
If it's not too much trouble, could you create a minimal demonstration of a simple piece of code, structured for various goals - easy to extend, easy to debug etc.? I can't defend my code form the best-practice-people with a Pareto Front wikipedia article.
- ryandv 3y agoThere's two aspects to GP's comment. > Even in the best case, readability just becomes a Pareto frontier[0], given by expressive limits of the dominant programming paradigm > People forget that readability isn't a function of specific program - there is no one optimal readability. On the contrary, it's a function of the program and the goals of the reader. The original Wiki at c2 has a great example [0] comparing the expressive capabilities of functional vs. object-oriented programming, and their suitability towards certain goals - namely, either extending the set of operations the system supports, or expanding the number of data (sub-)types the system models. In spite of Turing equivalence, some paradigms (even if only in terms of readability, dev ergonomics etc.) are better suited for expressing certain classes of problems than others, which may introduce unnecessary friction trying to solve problems that are mismatched with the paradigm's approach to structuring and decomposing problems (e.g. into compositions of functions, or compositions of objects). [0] https://wiki.c2.com/?ExpressionProblem https://wiki.c2.com/?ExpressionProblem
- pjc50 3y agoI'm not sure this is even possible - all the value comes when the underlying application is no longer simple. If you try to make a minimal example it just looks over-engineered, like some sort of "enterprise hello world" joke.
- actionfromafar 3y agoWith enough work I think it is definitely possible, but your comment made realise it would be pretty large, almost a research project. One could start from a real case in a real company, document it thorougly, including different stakeholders. Then rewrite the code to fit this organisation at this point in time. Then, make a two or three fictional changes to the organisation and circumstances, snapshot these (or follow an organisation longitudinally for long enough that this occurs naturally) and for each snapshot, rewrite and redocument the code to fit those circumstance. From that, one could "dumb down" the whole thing until it stops making sense and see how simple one could make it. Probably there are people smart and seasoned enough to write an entirely fictional account of all of this, and still have it make sense - that's not me though.
- TeMPOraL 3y agoHow about just hello world? public class HelloWorld { public static void main(String[] args) { // Prints "Hello, World" in the terminal window. System.out.println("Hello, World"); } } This is the full code. This is what I care about on success path: System.out.println("Hello, World"); // Success Or maybe even just: println("Hello, World"); Or maybe, because I forgot what is what in Java: java.lang.System - The System class contains several useful class fields and methods. It cannot be instantiated. | | System.out : java.io.PrintStream - The "standard" output stream. | | | | PrintStream::println(String) -> void - Prints a String and then terminate the line. v v v System.out.println("Hello, World"); This is what I care when I'm looking at the module view: HelloWorld (public, class) main(String[] args) -> void (public, static, entry point) -- Prints "Hello, World" in the terminal window. This is what I care when I'm looking at error propagation view: HelloWorld::main() - entry point Program end, return code 0 [default] Or maybe, given sufficient metadata in the standard library: HelloWorld::main() - entry point System.out.println("Hello, World") -> failed if System.out.checkError() == true Program end, return code 0 [default] Or I want a dependency view: HelloWorld java.lang.System [java.io.PrintStream] Etc. Now imagine being able to open the Hello World code, and instantly switch between those views and many others with a single shortcut. Not tooltips above the code, but views that replace code. That is what I'm talking about. Oh, and views are editable where it makes sense. Even read-only views would improve the development experience a lot, but the magic is in mutable views, so that you don't ever have to touch the full, original form of the source. EDIT: look at the first vs. third code-block in this comment. People built whole programming languages on the premise that Hello World should look like the third block instead of the first one. That's an extreme case of making a style choice ahead of time, and also a source of endless, pointless debates.
- pjc50 3y agoInteresting, and somewhat doable for IDEs in current languages, but I think the real question is: is it possible for what you can't see to hurt you? That is, if typing in one of the restricted views, is it possible to create a bug because of something that's currently hidden from you? I feel as soon as that happens to someone, they are going to switch to the "show everything" view and never switch back. > look at the first vs. third code-block in this comment. People built whole programming languages on the premise that Hello World should look like the third block instead of the first one. Well that was silly of them. Microsoft managed to retrofit it: https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/top-level-statements https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/to...
- TeMPOraL 3y agoThink "lots of small functions" vs. "few fat functions" - one of those infamous code style holy wars. Look at the arguments people make for and against either. There is no single answer there, because which style is better depends on what you're doing. For example, "lots of small functions" makes things easier to understand when you're working horizontally, trying to e.g. understand a module at a certain level of abstraction. However, in the same code, if you're trying to understand a single piece of functionality, e.g. to debug it, it's much easier when you have a vertical view - ideally a single fat function with all helper calls inlined. In first case, all the little functions form high-level languages that aid your understanding; in the latter, they're just noise that kills your working memory with all the jumping-to-definition around the codebase. Our current programming paradigm forces you to make this style choice ahead of time. You can't have it both ways. This is the Pareto frontier - as you make your codebase easy for one type of work, it becomes hard to do other kinds of work in it. And this is a stupid state to be in, because you will be doing both horizontal and vertical tasks, and many others that benefit in yet different kinds of slicing through code, and you will be switching gears every few days or weeks. Another concrete example: exceptions vs. algebraic return types (Expect/Result/Maybe/etc.). People love the latter for code locality, and mostly ignore the ridiculous amount of noise this method adds to all code, and/or invent ever more advanced math to paper over it. Exceptions were much better in this regard, if worse in others, but again, I posit that having to make that choice is dumb in the first place. Personally, I'm fine with Result return types. It's just that, 90% of the time, I don't give a damn about them, because I'm working on the success case/golden path, and they're just pure visual noise. It's something I'd like to just not see. But then, remaining 10% of the time, I'd like to make everything other than Result types and control flow disappear, because when working with error handling, success case becomes visual noise. Inventing new species of monads or syntax keywords to cram this, and async, and other cross-cutting concerns, isn't the solution. The solution is to stop working on raw plaintext source code, and instead work on representations tailored to specific needs, while treating the underyling source code like we treat assembly today.
- dale_glass 3y ago> Another concrete example: exceptions vs. algebraic return types (Expect/Result/Maybe/etc.). People love the latter for code locality, and mostly ignore the ridiculous amount of noise this method adds to all code, and/or invent ever more advanced math to paper over it. Exceptions were much better in this regard, if worse in others, but again, I posit that having to make that choice is dumb in the first place. There's actually at least one programming language that allows you to choose as needed, and it's Visual Basic of all things. The "On Error Goto" directive says on error you want to jump to an exception handler. "On Error Resume Next" means just keep forging ahead -- which is a terrible idea done badly, but if check the Err object, you can access the status. It's not quite as good as algebraic return types, but it was an interesting idea in that you can code each bit of code in whichever way works out best.