Live data from Hacker News

Cyclic dependencies are evil (2013)

fsharpforfunandprofit.com

1–10 of 125 posts

Re: Cyclic dependencies are evil (2013)

#2
EDIT: In fact I appear to have paraphrased the next post in the series, https://fsharpforfunandprofit.com/posts/removing-cyclic-depe... . Probably go and read that instead.

One pattern this nudges you towards is having a Domain.fs at the top of each project. Since everything in your project wants to talk in terms of the data types you've modelled, it makes sense to put them all in the same place at the top. Moreover, once you've done that, you're guided towards having your data types really being "dumb" - algebraic data types only - because to put actual behaviour into them is harder when all you have is definitions of data types (and no associated modules). You certainly can write OOsagne using the Domain.fs pattern, but it's much harder and the code really smells when you do (because the domain file gets super long).

The upshot is that your domain model appears explicitly at the start of the project, which is a big win for anyone who comes into the project and needs to learn quickly what's going on. By contrast, nearly all the C# I've ever come across has the domain spread across many files and all mixed up with implementation details.

This is certainly not the only way to write F# - I've written projects which have the domain spread across multiple files - but it's one nice way to handle a small-to-medium-sized project.

Re: Cyclic dependencies are evil (2013)

#3
Language constraints aside, the real world is not something that can be cleanly modeled without the notion of circular dependencies between things. Not very many real, practical activities can be truly isolated from other closely-related activities and wrapped up in some leak-proof contract.

Consider briefly the domain model of a bank. Customers rely on Accounts (I.e. have one or many). Accounts rely on Customers (i.e. have one or many). This is a simple kind of test you can apply to your language and architecture to see if you have what it takes to attack the problem domain. Most approaches lauded on HN would be a messy clusterfuck when attempting to deal with this. Now, if I can simply call CustomerService from AccountService and vice versa, there is no frustration anymore. This is the power of reflection. It certainly has other caveats, but there are advantages when it is used responsibly.

If you want to understand why functional-only business applications are not taking the world by storm, this is the reason. If it weren't for a few "messy" concepts like reflection, we would never get anything done. Having 1 rigid graph of functions and a global ordering of how we have to compile these things... My co workers would laugh me off the conference call if I proposed these constraints be imposed upon us today.

Re: Cyclic dependencies are evil (2013)

#4
I’ve played around with F# over the years, but have only recently started getting into seriously. The top down nature of dependencies (both within a given file and for the files within a project) is a little odd at first, but once you get used to it feels quite natural.

If nothing else, it encourages (somewhat) common ways of structuring projects and avoids a lot of bike shedding about separation of concerns and project structure I encounter in C#.

Re: Cyclic dependencies are evil (2013)

#5
Nice article. The first thing that came to mind when seeing the title was "but circular dependencies just mean that your layers are wrong and those should all be in the same layer" and funnily enough that's exactly what's explained in the article!

What would be interesting would be to organize modules into named layers--instead of just explicit 1-by-1 module dependencies (i.e. edges). I have not seen a language do that yet.

Another interesting thing that I haven't seen touched on in more mainstream languages is the idea of bidirectional interfaces. The somewhat DSL-like NesC language had this, primarily driven by the need to write device drivers that serviced interrupts (and events).

Re: Cyclic dependencies are evil (2013)

#6
post #3

Language constraints aside, the real world is not something that can be cleanly modeled without the notion of circular dependencies between things. Not very many real, practical activities can be truly isolated from other closely-related activities and wrapped up in some leak-proof contract. Consider briefly the domain model of a bank. Customers rely on Accounts (I.e. have one or many). Accounts rely on Customers (i.…

I don't understand how reflection is involved here? Don't you just have a data model (schema) that can be interacted with?

Re: Cyclic dependencies are evil (2013)

#7
post #3

Language constraints aside, the real world is not something that can be cleanly modeled without the notion of circular dependencies between things. Not very many real, practical activities can be truly isolated from other closely-related activities and wrapped up in some leak-proof contract. Consider briefly the domain model of a bank. Customers rely on Accounts (I.e. have one or many). Accounts rely on Customers (i.…

In F#, you would naturally approach this by defining a Customer independent of the Account (e.g. just containing a name and address), and an Account independent of the Customer (e.g. just containing an ID), and then a Bank which is a mapping of Account to Set. What you see as a cyclic dependency, I see as a data type that you haven't reified.

Re: Cyclic dependencies are evil (2013)

#8
post #3

Language constraints aside, the real world is not something that can be cleanly modeled without the notion of circular dependencies between things. Not very many real, practical activities can be truly isolated from other closely-related activities and wrapped up in some leak-proof contract. Consider briefly the domain model of a bank. Customers rely on Accounts (I.e. have one or many). Accounts rely on Customers (i.…

I’m having a hard time understanding why you think F# is unable to handle the domain model presented.

Re: Cyclic dependencies are evil (2013)

#9
I still cringe when I think back to some C projects from long ago, where the dependency chains of headers and libraries where unfathomably byzantine.

On a related note, lately I have been looking into some biochemistry topics and their relation to computer science. It seems that cyclic dependencies are possibly a requirement for life, which makes faithful simulations of biochemical processes an interesting challenge.

Re: Cyclic dependencies are evil (2013)

#10
For my FE projects I employ a module based code structure. If you import a module, you get the whole thing. This lends itself to many positives but one negative is it makes it easy to run into circular dependencies. I wrote an article discussing my architecture and how I solve circular dependencies in js.

https://erock.io/scaling-js-codebase-multiple-platforms/

In the article I argue that circular dependencies are a good thing because they uncover poor code organization.

Post reply on HN