Live data from Hacker News

Fighting Complexity in Software Development

github.com

31–40 of 117 posts

Re: Fighting Complexity in Software Development

#31
post #25

I'm sure this is partly because I don't read F#, but it looks like they've moved all the complexity into meta-programming madness, this is just being way to clever to play code golf at a high level, this is exactly the sort of complexity we should be fighting against. Even the initial c# version was over complicated. The complex fluent interface with lambdas and callbacks could be done with a few if statements that w…

The problem is when you want validation errors which contains the field name, and a descriptive error message. Oh you want them localised as well?

You then want each field to be validated individually. So you get an error for each field which is wrong.

So you have if statements for each field creating a localised validation error object then placing in a list.

You have 8 fields coming in on your request. It's starting to look like a big method now with 8 if statements creating these localised validation objects.

You also want to share your validation rules between different use cases.

FluentValidation makes that quite quick and terse to achieve compared to simple if statements.

Re: Fighting Complexity in Software Development

#32
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 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 sum types (Rust enums), a better type system, an unforgiving compiler, async/await, a better module system, lifetime checking, and an ecosystem of easy-to-grok libraries.

These things just make bugs disappear.

When it comes to IDE experience, the parts that I use often are mostly the same between Rust and our language.

Edit: I'd say it's both, in a multiplicative manner. You need experience and a good set of tools (the language itself being the most important tool) to write good code fast.

Re: Fighting Complexity in Software Development

#33
post #27
post #22

Earlier quoted context omitted.

Which is a longish way of giving the answer no one wants to hear: Experience is everything.

Erm surely ability is important as well. Programming is no different in this regard to pro sports - some people have more talent (which probably in turn breaks down into innate attributes, determination and learning opportunity earlier in life).

Ability comes from practice, there really are no shortcuts.

Most of the difference seem to be in motivation.

Re: Fighting Complexity in Software Development

#34

I love F#, but using F# instead of (type|java)script would add a lot of complexity to my 'full stack'. Let's see I replaced my node.js backend with an F# one, the following issues would arise: 1. I now have two different languages for client and server, and can't share e.g. validation code. 2. Dealing with 2nd class linux support (no REPL) 3. No library that combines the maturity and simplicity of express.js. Yes I a…

What would the concrete implementation of the at class that represents the deactivated credit card look like?

It would be an abstract class with an abstract processPayment method. Then two concrete classes that implement it, each with their own implementation of processPayment.

https://en.wikipedia.org/wiki/Expression_problem

Re: Fighting Complexity in Software Development

#36
post #10

Earlier quoted context omitted.

I really don't think it adds complexity. Sure, it's going to be different , so there's a mental hurdle to clear in learning how a new stack works. That doesn't mean it's going to be more complex . > 1. I now have two different languages for client and server, and can't share e.g. validation code. You could use Fable to transpile F# to Javascript, keeping a single language > 2. Dealing with 2nd class linux support (no…

Hi, thanks for the open minded response. It's an issue I enjoy discussing. You could use Fable to transpile F# to Javascript, keeping a single language That seems like another explosion of complexity. Source maps, mapping F# to a JS constructs when debugging, niche tooling, wrapping other JS libraries in a nicely typed F# package... IME it's best to avoid transpiling anything more exotic than typescript. FSI is avail…

I think these usually end up with two people agreeing to disagree :)

Yes, you do lose source maps by transpiling, but in my (albeit fairly limited experience), the type checking means I have drastically less debugging to do in the first place. You're right, though, the tooling leaves a lot to be desired (and this is also on the assumption you have TS definitions for third party libraries - I agree it becomes a lot more difficult if you don't).

FSI is available in both Mono and .NET Core 3 (which is still in preview).

Re: Fighting Complexity in Software Development

#37
post #17
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…

but have you ever had to maintain a ruby project after the first year? The cost just goes up and up, and I think it’s because the language is so hostile to static analysis.

Yes. I've been working on an corporate internal RoR tool that launched in 2010. Various engineers over the years continued releasing new features and updating language/framework development... when I earlier this year, development/maintenance cost was no higher than any other software of that nature and age.

Cost only goes up and up when engineers go overboard with "clever" Ruby magic... which is human error, don't blame the tool.

Re: Fighting Complexity in Software Development

#38
post #31
post #25

I'm sure this is partly because I don't read F#, but it looks like they've moved all the complexity into meta-programming madness, this is just being way to clever to play code golf at a high level, this is exactly the sort of complexity we should be fighting against. Even the initial c# version was over complicated. The complex fluent interface with lambdas and callbacks could be done with a few if statements that w…

The problem is when you want validation errors which contains the field name, and a descriptive error message. Oh you want them localised as well? You then want each field to be validated individually. So you get an error for each field which is wrong. So you have if statements for each field creating a localised validation error object then placing in a list. You have 8 fields coming in on your request. It's startin…

> The problem is when you want validation errors which contains the field name, and a descriptive error message. Oh you want them localised as well?

So the above example would become something like this:

  if (!string.IsNullOrEmpty(card.CardNumber) && CardNumberRegex.IsMatch(card.CardNumber))
    validationContext.add("CardNumber", Localizer.MessageFor("InvalidCCNumber"));
  if (x.ExpirationMonth  12)
    validationContext.add("ExpirationMonth", Localizer.MessageFor("InvalidCCExpiration"));
Throw in some lambda's for the property name and static strings for the message names if you really need to be type safe. Also I'm not sure if FluentValidator handles this, but you need somewhere for root level errors, not all errors map neatly to a property.

> You have 8 fields coming in on your request. It's starting to look like a big method now with 8 if statements creating these localised validation objects.

There's no local state, the errors are stored in a glorified dictionary, it's a simple imperative series of if statements that anyone who's gone beyond hello world in any language can understand. Big methods are not bad just because they're big (not that 8 if statements is big), they're bad when there is a lot of mutable state that the programmer has to track in their head, validation logic rarely has this problem. It would be fine if there were 1000 properties because the complexity is flat.

> You also want to share your validation rules between different use cases.

So you make a function. It doesn't look like FluentValidator offers any improvement here, it seems like custom rules with this library basically just wrap a function call: https://fluentvalidation.net/start#including-rules or you create a "function" at runtime with rulesets: https://fluentvalidation.net/start#including-rules

> FluentValidation makes that quite quick and terse to achieve compared to simple if statements.

From the examples I'm not sure it's any quicker or more terse after you include the extra boilerplate setup. All it seems to do is turn if statements into where/must calls, for loops into RuleForEach calls and functions into custom RuleSets. It also adds the complexity of using a library.

Re: Fighting Complexity in Software Development

#39
post #17
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…

but have you ever had to maintain a ruby project after the first year? The cost just goes up and up, and I think it’s because the language is so hostile to static analysis.

Have you maintained anything after the first year where that wasn't the case? Especially if you had a high degree of churn on the developers.

I'll grant that it is easier in more stable API environments. But we are our own worst enemies in that race.

Re: Fighting Complexity in Software Development

#40
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.

"Started from Scratch". I have never seen any project where something has been started from scratch actually turn out well.
Post reply on HN