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 actually don't follow your example; I don't see why this is cyclic. In your example what exactly would CustomerService be responsible for that prevents it from functioning unless it has a reference to AccountService? AccountService is pretty obvious (add/remove money, link other accounts, close account, etc.) but I'm struggling to see what CustomerService would do on a per-customer basis that it would need a refere…
Cyclic dependencies are evil (2013)
121–125 of 125 posts
Re: Cyclic dependencies are evil (2013)
#122I’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 proj…
What I really wanted to say was: "F# lets us be lazy. You write way less code, you have fewer things to keep track of, you need fewer abstractions, you can write everything in the most straightforward way possible and then extend only when necessary because refactoring is super safe."
What I _actually_ said was: "F# is an extremely rigid language. It will not let junior developers take shortcuts, because you must write your code properly or it won't compile. Your classes and functions must be written in the correct hierarchical order, you must cover every corner case. I know it's going to be stressful or boring to be forced to do things right every time and never be able to just push some sloppy cowboy fix, but it's a sacrifice we're willing to make :)"
Re: Cyclic dependencies are evil (2013)
#123Earlier quoted context omitted.
Right. Often there are 2 types of interfaces in a project. The first are "natural" interfaces, that you have put some design into and are meant to be reusable. Things like Streams or Collections. When you write a function that uses one of these, you really are expecting to be able to use any implementation. If you want to go to the implementation of Stream.Read, obviously the IDE isn't going to be able to do it, it's…
Is there any solution to this?
Re: Cyclic dependencies are evil (2013)
#124Earlier quoted context omitted.
Right. Often there are 2 types of interfaces in a project. The first are "natural" interfaces, that you have put some design into and are meant to be reusable. Things like Streams or Collections. When you write a function that uses one of these, you really are expecting to be able to use any implementation. If you want to go to the implementation of Stream.Read, obviously the IDE isn't going to be able to do it, it's…
Is there any solution to this?
The fact our solution has an interface for just about everything for testing reasons doesn’t slow me down even in the slightest when I’m looking through the code.
Re: Cyclic dependencies are evil (2013)
#125Earlier quoted context omitted.
In a relational database you would have a CustomerAccount table keeping track of which accounts that belongs to which customers. Customer would not know about Account, and vice versa. And what has reflection to do with this?
Reflection allows you to put the interfaces to Account and Customer into a shared module and the business logic implementations into their own mutually independent modules, thus removing the cyclic compile time dependency. You "wire up" the implementations at runtime, using reflection.