Live data from Hacker News

Fighting Complexity in Software Development

github.com

61–70 of 117 posts

Re: Fighting Complexity in Software Development

#61
post #13

I feel like I’ve responded this before, but I feel like people often attribute their increased knowledge of how to develop systems without bugs to the new fancy language they switched to. Fact is they could build better software in the old language as well, assuming they started from scratch.

I'd agree, but some tools just make it easier to design and build a complex system whatever the level of experience of the programmer(s), designers and so on. This programming language and IDE https://en.wikipedia.org/wiki/Clarion_(programming_language) is behind some of the biggest databases in the world. Because of the openess of the IDE, in one instance it was possible to migrate one country's main cancer charity app from ISAM files to MS SQL, and rewrite it from procedural to OOP code in just two hours! Admittedly it took a week to build a program to do the coding changes, but that program became a tool in its own right to migrate other programs, but the original devs thought it would take a human 3months to do the work, which is already several months less than if the program was written in another language!

These are just some of the big corps who use Clarion. https://en.wikipedia.org/wiki/LexisNexis https://en.wikipedia.org/wiki/DBT_Online_Inc. https://en.wikipedia.org/wiki/Experian

Various banks and other stock market listed companies. Even various military use it for their own top secret work.

The key to its success is the template language, which enables the programmers to work at a higher level of abstraction which for some reason just doesnt seem popular amongst many programmers. You can use the templates to write code in other languages, including Java, PHP, ASP.net, javescript and more.

Its safe to say, that everyone in the Western world will have some of their details stored in a Clarion built database, and its not just limited to building databases, its even been used to build highly scalable webservers. Theres also C/C++, Assembler and Modula-2 built into the compiler, so you can get right down to low level coding if required, and there's a Clarion.net version which is mainly like C# but has some of the data handling benefits of F#.

Re: Fighting Complexity in Software Development

#62
post #28

Earlier quoted context omitted.

Agree. You can write terse, maintainable, well encapsulated, testable and readable code in most any language. The problem is about the humans not the language they select. But yes, complexity is also a major problem.

What I have learned is that what makes a language (or platform, or tool) "good" isn't how easy it is to write good code, but how hard it is to write bad code. Does a beginner following the path of least resistence, on a tight schedule, end up with maintainable code or not? I'd argue that this is the weakness with (the traditional) OO languages. An experienced developer with plenty of time can write good software with…

>isn't how easy it is to write good code, but how hard it is to write bad code

In many languages they make it harder to write bad code but they do so at the expense of delivering functionality quickly. There's a clear trade off there - one which is often very project dependent (some projects primarily need to develop functionality quickly; others prioritize stability).

The problem of slowing down development becomes particularly pronounced when developing something where the biggest risk isn't building the thing wrong, but building the wrong thing. It's extremely expensive to use a very strict language if you're developing code where requirements are highly in flux and cannot be discerned up front.

Ideally general purpose languages should enable a smooth transition from coding up a prototype/MVP all the way to production-hardened, spotlessly clean code.

I like rust a lot but I would only use it to write very low level code where the requirements are cast in stone and speed and stability is of the utmost importance. It's a lovely language but it's very slow to build stuff in, and in almost all cases it should be used to rewrite something existing rather than to build it anew.

Re: Fighting Complexity in Software Development

#63
post #8

In mature OOP you have ways to write nice models and have good validations. https://guides.rubyonrails.org/active_record_validations.htm... I will argue that the complexity of software development is not because of OOP vs Functional. Tooling, documentation, quality of libraries and people are what matter most. Ruby was a massive success is largely attributed to above. We are humans, we can understand and deal with a…

> competing half finished implementations (lisp) As well as one of the most complete specifications in ANSI Common Lisp.

I'm curious about lispers. I thought quicklisp made a lot of things frictionless.

Re: Fighting Complexity in Software Development

#64
post #13

I feel like I’ve responded this before, but I feel like people often attribute their increased knowledge of how to develop systems without bugs to the new fancy language they switched to. Fact is they could build better software in the old language as well, assuming they started from scratch.

It does play but no. Languages and paradigms do make a difference. I had to come up with a tiny DP answer for a java interview and it was a massive burden. Even though I could write the same (quality and perf) version in other languages in 2 minutes.

Re: Fighting Complexity in Software Development

#65
post #56

Earlier quoted context omitted.

I strongly disagree. We use a strongly typed Lua-like language at my company and it has everything you need to build decent applications, but we hit so many bugs. It took me 12 hours over 5 days to make a simple modification to the business logic (half of that was figuring out and fixing bugs). It took me 4 hours to write something far more complex in Rust with virtually zero bugs; I attribute this almost entirely to…

I attribute this almost entirely to sum types (Rust enums), a better type system, an unforgiving compiler, async/await, a better module system, lifetime checking... This seems like an example of a language effectively abstracting common complexities and pain points, which were probably discovered in earlier languages...

I think it's fair to say that rust is the first mainstream languages bringing these notions out of the woods. Who on earth knows about ML or cyclone ? 0.0001% of the programming crowd maybe.

World operates in spirals. We branch off trying things and then go back to old forgotten ideas, etc etc

Re: Fighting Complexity in Software Development

#66

Earlier quoted context omitted.

What I have learned is that what makes a language (or platform, or tool) "good" isn't how easy it is to write good code, but how hard it is to write bad code. Does a beginner following the path of least resistence, on a tight schedule, end up with maintainable code or not? I'd argue that this is the weakness with (the traditional) OO languages. An experienced developer with plenty of time can write good software with…

>isn't how easy it is to write good code, but how hard it is to write bad code In many languages they make it harder to write bad code but they do so at the expense of delivering functionality quickly. There's a clear trade off there - one which is often very project dependent (some projects primarily need to develop functionality quickly; others prioritize stability). The problem of slowing down development becomes…

I agree - in a prototyping phase it may be beneficial to be able to throw something together. The problem is that what you throw together is invariably the base for the real thing. The motto of "design one to throw away" is great, but I haven't seen it applied as much as it should.

Using a "stiff" set of tools might slow down the first stages of prototyping, but it also makes the prototype easier to modify as requirements change. The question I suppose is simply where the equilibrium occurs. I.e. does Rust or F# make a thing that is easier to modify (because of less coupling) already after one or two months, or only after one or two years?

Re: Fighting Complexity in Software Development

#67
I think the problem with OOP is that it is merely a pattern and yet has been integrated into many languages in a very prominent way. This can mislead people into thinking it's something more fundamental and generally applicable - but it's not, it's just another pattern, which for some things works great, and for others is terrible. Just like when you read that aweful code that someone wrote just after reading a book on pattern x and forced it upon a project, the difference is OOP is forced on almost everything.

Once you realise this it's fine, you just don't use those features when it doesn't make sense.

Re: Fighting Complexity in Software Development

#68

Earlier quoted context omitted.

>isn't how easy it is to write good code, but how hard it is to write bad code In many languages they make it harder to write bad code but they do so at the expense of delivering functionality quickly. There's a clear trade off there - one which is often very project dependent (some projects primarily need to develop functionality quickly; others prioritize stability). The problem of slowing down development becomes…

I agree - in a prototyping phase it may be beneficial to be able to throw something together. The problem is that what you throw together is invariably the base for the real thing. The motto of "design one to throw away" is great, but I haven't seen it applied as much as it should. Using a "stiff" set of tools might slow down the first stages of prototyping, but it also makes the prototype easier to modify as require…

>The problem is that what you throw together is invariably the base for the real thing.

This isn't invariable at all. More often what you throw together gets thrown away. I'd estimate this happens to more (working) code I've written over my career than not. The hardest thing to get right is often getting the contours of a tool right and ascertaining what it should do - not making it work right after it has proven itself.

>Using a "stiff" set of tools might slow down the first stages of prototyping, but it also makes the prototype easier to modify as requirements change.

This is only really the case where the prototype was fundamentally solving the right problem in the right way to begin with and the subsequent changes are incremental in nature. If the design of, say, a microcomponent is flawed from the outset or it did the wrong thing and you have to re-do it, those "stiff" tools slow you down.

Using an extremely strict set of tools in a prototyping environment also invariably means a lot of extra up front work dealing with the tools' attempts to protect you from bugs which have an extremely low probability of occurring and/or an extremely low cost when they do occur.

If F# or rust or haskell really was quicker and more effective in a prototyping environment as well as when writing production hardened code, programmers would likely eventually converge on only using them. That isn't what is happening.

Re: Fighting Complexity in Software Development

#69
``` type CardNumber = private CardNumber of string with member this.Value = match this with CardNumber s -> s static member create str = ```

Haha, no thank you

>OOP languages for modern applications gives you a lot of troubles, because they were designed for a different purposes

For which purposes if not software development exactly?

Re: Fighting Complexity in Software Development

#70
I really support this kind of writing, I don't think this kind of stuff is written about enough, and it's exactly what everyone learns the hard way working on software projects. Skill wise, knowing the kinds of reasoning/techniques that articles like these discuss is the difference between "junior" and "senior" developers (though I very much dislike those terms).

One thing I want to point out -- if at all possible do not use decimals for money:

> We could use decimal (and we will, but no directly), but decimal is less descriptive. Besides, it can be used for representation of other things than money, and we don't want it to be mixed up. So we use custom type type [] Money = Money of decimal .

The custom type is a great idea (try to write code in languages that make this concept easy, I suggest Haskell & type/newtype). The problem here is that decimal is the wrong type for storing money[0]. Your first IEEE754 floating point bug teaches you this, but in general trying to write code around manipulating decimals can get very messy really quickly when precision is involved in any case. Another example is JSON, JSON numerics are actually all floats under the covers, so this means if you store more precision or a bigger number than it can handle, things can get wacky if you're not careful -- this is one of the places where being "stringly typed" (and defining your own unpacking to go with your domain types) can be very helpful.

Libraries like dinero.js[1] exist because of how surprisingly hard this problem is, kind of like how moment[2] exists due to how hard dealing with time can be.

[0]: https://stackoverflow.com/questions/3730019/why-not-use-doub...

[1]: https://github.com/sarahdayan/dinero.js

[2]: https://momentjs.com

Post reply on HN