Connascence of Value

We’re looking at connascence of value next, which is the 3rd level of dynamic connascence and the 8th level of connascence in general. You really don’t want to have any of this connascence in your system, as it is a doozy. Oh boy.

Connascence of value refers to when multiple components must agree on the value of a particular piece of data implicitly- as in, they all hold their own reference to this value, and if the value changes then all of the components must change too. We’re still in dynamic connascence, so you won’t get any help at compile time- this is going to blow up when you run the program.

You get connascence of value when one component knows about a particular value in another component implicitly- without being told that value by any other component. This means that when you change the value in one of the components, you have to remember to change the other one too, or it’s going to break. You’ll see this type of connascence a lot between production code and test code- most often in the early stages of the TDD cycle, but it can persist if the production code and tests aren’t refactored adequately during the refactor step, too. This crops up in components in production systems too- where a class knows about another class’s internal state and acts based upon that knowledge.

Ok, let’s have a look at some concrete examples of connascence of value, firstly in the more abundant coupling between production and test code.

We’ve got some really basic connascence of value here- both the GiftShop and the GiftShopTest class know about what the current total should be at that point in time. If you change the value in one place, you have to change it in the other.

This usually isn’t a problem when we’re following TDD, as the next tests we write will make the test suite more specific, which will force us to make the production code more generic, given adequate refactoring. However, connascence of value between the test code and the production code can often end up being left in place if a refactor step is skipped.

But how would we get rid of this connascence of value at this point? We currently don’t have a way to explicitly “tell” the gift shop anything about prices, so we need to introduce that at this point. There’s a whole bunch of ways we can do this- a constructor parameter, passing the price into the scan method, bundling the item name and item price into an Item object and passing that into the scan method… whichever we do, we’ve removed the implicit knowledge of the price existing in both components and made it explicit, removing the connascence of value.

We’ve chosen to encapsulate the data about the item in an Item class, which just has a name and a price currently. Because we no longer implicitly rely on the price of the T-Rex Keychain being 250 in both the production code and the test code, we have gotten rid of the connascence of value.

However, there is still connascence of value within the test itself- the value 250 appears in two places in the test method, and if one of them changes then the other one would have to also. This usually isn’t a problem, as the values are right there next to each other- but you can get rid of this connascence of value by reducing it to connascence of name by introducing a constant instead of referencing the value itself twice. This can make tests harder to read, so there’s a balancing act here.

Connascence of value can also appear between software components in production code, where it can do much more damage. Sticking with the commerce theme, we’re going to look at a small section of a fulfilment system (for the buying and selling of dinosaurs, of course). We need to make sure we’re shipping dinosaurs quickly, but also ensure that we don’t ship any that haven’t been paid for yet. A simple example of what the system could end up looking like is below:

This code is a small and self contained example of what the code could look like for this system- it almost definitely wouldn’t look like this, as there would be many moving pieces across multiple different modules. The point is that even with such a small toy system we can introduce connascence of value that would be problematic, and many times more troublesome in a real commerce system.

The connascence of value we’ve introduced here is related to that number 23, and not only in the more obvious “it’s a magic value” way. For those curious, in our third party payment provider, 23 means “Payment successful”, which seems to fit our requirements nicely. Could removing the hard-coded 23 and replacing it with a constant like PAYMENT_SUCCESSFUL remove our connascence of value? Almost, but not quite- as we know, connascence of value refers to when one component must change if another component changes a value. The value here isn’t necessarily the physical number 23, it’s the implicit value of “a payment that is successful”, or to match our requirements even closer “a payment status that indicates fulfilment can proceed”. So at the point values are introduced that effectively mean “payment successful” for our fulfilment engine but aren’t necessarily the number 23, we’ve got to make changes. And if we’re introducing connascence of value around our complicated commerce codebase by knowing implicitly that 23 is “payment successful”, we’re going to be making a lot of changes in a lot of places to handle the new cases of “payment accepted”, “payment successful with 3D secure failure”, “payment successful with 3D secure skipped”, and anything else that gets added in the future.

So, what can we do to limit the impact of this connascence of value? We need a way to say “any and all result codes that mean we can continue with fulfilment”, at least for this case. Maybe we could be more generic and say “any result code that means payment has been successful”. But the important part is that we put this in one place under our control, so our connascence of value doesn’t end up spiralling all over the codebase and cause havoc. Let’s make some small changes.

All we’ve done is move the connascence of value from being between the PaymentDetails (And the payment provider) and the OrderFulfilmentSystem (And everywhere else it was used or will be used in the future) and replaced it with connascence of value between the PaymentDetails and the Order class. It’s probably impossible to remove the link between what a “successful payment” means and whether an order can be fulfilled, but this way we have limited the scope of those changes, and ensured the cast majority of our software components are insulated from that change proliferating through the codebase.

Connascence of value is a tough one to get rid of except in the most obvious of cases- because it’s subtle and easy to introduce. As you’re designing individual components of a system, you’ve got the whole system in your mind, so it is all too easy to include the assumptions about the state of the rest of the system in components that shouldn’t necessarily know about that, rather than putting in the right abstractions to communicate those assumptions explicitly.

Connascence of Timing

Connascence of timing is our 2nd level of dynamic connascence and our 7th level of connascence in general. Things are getting pretty serious right about now and we’re at the point that we don’t want to be ignoring any connascence we find at this level.

Connascence of timing refers to when multiple components must agree on the timing of particular executions. We’re talking dynamic connascence here, so once again it’s something we can only observe and reason about in relation to runtime objects rather than compile time classes.

You can get connascence of timing when one component presumes to know how long a different component’s operation is going to take- you’ll usually see this expressed as Thread.sleep() or something similar. Anyone that’s ever used Selenium for UI testing knows how dangerous this can be. There’s also the case where we’re using distributed systems with eventual consistency that can have an impact with connascence of timing if we’re not careful.

Let’s see a real life example of how this might come about and what issues it could cause.

We’ve got connascence of timing here, as the transfer station presumes to know that after registering a dinosaur for transfer, there’s a 25 second delay before the registration goes through and the dinosaur can be shipped. And this might be true- currently. What happens if the process takes a bit longer than expected? The dinosaur won’t be shipped successfully and we’ll have to try again. What if the registry doesn’t have to check the no fly list any more, because we’re actually shipping them by cargo container on a ship? The process may only take 3 seconds in that case, but the transfer station will still be waiting for 25 seconds for no reason.

What can we do about this? One technique is to use retries with exponential back-off periods, so trying after 1 second, 2 seconds, 4 seconds, etc. until it succeeds. This still gives us connascence of timing relating to what we set our eventual complete timeout to be, but it’s less strong.

Alternatively, we could completely ignore the timing of the call and use callbacks/promises/observables/subscriptions instead- which are all a similar pattern of asynchronous processing with no timing requirements. Entire books have been written about each of these techniques, so we’ll just pick a simple one to demonstrate how it removes connascence of timing from our transfer station.

We’ve created a Callback interface with a single invoke() method, which we’re going to use to remove the connascence of timing between our two components. TransferRegistry now takes a Callback as part of it’s registerForTransfer() method, and will call the invoke() method on that callback when it’s finished registering. Our transfer station wraps the logic it was performing originally in a lambda and passes it through as that Callback. The transfer station is now no longer reliant on the registry completing in a certain amount of time- the callback will be handled as soon as the registry is complete.

This does have the side-effect of returning out of the transfer method straight away rather than 25 seconds later like before. I like to see this as a benefit- but if that’s something that’s required we could use exponential back-off in a retry mechanic instead, to at least reduce the connascence of timing to something that is more sensible.

Connascence of timing is another one of those that you want to get rid of as soon as possible, as it can lead to a world of hurt when timings change- networks get faster, slower, execution takes longer or has more to do. And you can’t tell if everything is still going to work until you run it.

 

Connascence of Execution

We’re starting our journey into dynamic connascence now, which is a bit trickier than static connascence. Dynamic connascence causes problems that you can’t necessarily see from the source code, as they require knowledge of how the program behaves whilst running. You can think of it as connascence that affects objects instead of connascence that affects classes.

Anyway, I hope you enjoyed the post on connascence of position, because connascence of execution is the dynamic equivalent. Connascence of execution refers to when multiple components must agree on the order of execution of code.

There are two main kinds of connascence of execution- sequential and adjacent. Sequential refers to when something must be done in a given order (Such as setting a recipient on an email before sending it), and adjacent refers to when something must be done without any intervening steps.

Let’s have a look at something that must be done in a given order:

Alright, everything looks fine so far- we have an enclosure that requires things to be done in the specific order in order to safely lock up a dinosaur. And we have a handler that agrees on this order and knows the right way to lock an enclosure.

If this was to ever change- say for a door needing to be locked before it could be primed, then both the enclosure and the handler would have to agree on the new order of execution, and both be changed at the same time to ensure correctness. And as connascence of execution is dynamic- we can only infer the behaviour from what happens at runtime, so it’s not as easy to track down and fix if we get something wrong.

To combat this, we need a way to transform our connascence of execution down to a lower level- preferably connascence of name. Let’s look at how we might do this:

Our DinosaurEnclosure now only exposes the correct action that can be taken next- like a state machine. A completely unlocked enclosure can only be locked, which returns a locked enclosure that can only be primed, which returns a primed enclosure that can only be electrified, which returns a safe enclosure that cannot be modified.

This has removed our connascence of execution, as it is no longer possible to execute the methods in the wrong order- the names of the classes and methods returned guarantee that, giving us connascence of name instead.

As connascence of execution is a dynamic connascence, it’s probably not a good idea to ever leave it alone where possible- they’re a lot harder to reason about from source code and tend to be a lot harder to fix if they go unchecked.

 

Connascence of Position

We’re at the end of our journey into the static levels of connascence, with connascence of position as the last stop. Connascence of position refers to when multiple components must agree on the order of values.

The most obvious example of connascence of position are method arguments- these must appear in the same position in the caller as they do in the declaration, or things are going to break. There’s also the order of items in a data structure such as an array, and having multiple components relying on this being the same. We’re going to look at method arguments in detail, as there are a number of ways to mitigate connascence of position when talking about the order of arguments.

Take the following classes:

We have connascence of position between these classes around the order of the arguments passed in to the method- we send an alert by passing in the recipient, the sender, and the message. We have to make sure that we pass those arguments in that exact order, otherwise our message isn’t going to get where it’s supposed to go, which could be disastrous.

We can already see that the alert in our test is being sent incorrectly, but that’s ok. We’ll just run our tests, the issues will be found and a helpful error message printed to the console, and we can proceed to fix the problems.

That’s the output of our alertConfirmationContainsRecipient() test. You might have noticed that the error message is incorrect- the test for the recipient shouldn’t expect the value to be generic.person@soontobe.eaten, it should expect it to be john.hammond@ingen.com.

The issue is that also we have connascence of position within our test class- with the JUnit library we are using for our tests. This is because JUnit methods such as assertEquals() expect the parameters to be passed in a certain way- the expected value followed by the actual value. We passed them in wrong, so when something fails we end up with a confusing and incorrect error message.

We can solve connascence of position in a number of ways, which we’ll examine below.

Probably the most elegant way of solving this particular connascence of position issue is using named parameters- instead of relying on passing parameters in the same order in the call as the declaration, we can give each of the passed parameters a label that matches the declaration, and reduce our connascence of position down to connascence of name.

That would be great if we were writing code in Ruby or C#… or Python, or Ada, or a whole bunch of other languages. Our code is in Java, so we’re not quite so lucky. I suppose we could attempt to mimic the behaviour of named parameters by passing in a Map, with the keys as the names and the values as what we want to pass.

That’s not really as elegant as I was hoping. We’ve made our parameters a Map<String, Object> so we can pass different types in to our method even though we don’t need to currently. Unfortunately this gets rid of any type safety we get, which is a feature I quite like from Java. It’s less explicit in what arguments you can pass too, so we lose those compile time checks as well. There’s also a whole bunch of extra boilerplate we need in both the caller and the declared method, which isn’t brilliant either. What else can we do?

Well- it doesn’t solve the issue of extra boilerplate (not by a long shot), but there’s something we can do with type safety and explicit arguments. There’s a technique we can use called Tiny Types. Instead of passing in basic data types like String, Integer, Double, etc., we can wrap these up in objects representing domain concepts for each of the parameters- like Recipient, Sender, and Message.

Ok yeah that is a lot of boilerplate actually- but it has managed to reduce our connascence of position down to connascence of type. Try to pass the wrong type in and you’ll get an error rather than your message going to the wrong place or getting lost all together.

Tiny types can be really useful when you’re trying to express an actual domain concept that has behaviour- such as maybe recipient having to contain an @ sign, or message only being a certain number of characters. However, it’s probably overkill to use this technique as purely a method to remove connascence of position when your primitives won’t benefit in other ways by being promoted to full-blown domain objects.

Alternatively, we can use the Parameter Object and Builder patterns to reduce our connascence down to connascence of type. We’ll have a look at what the Parameter Object looks like first, but we won’t stop there:

Not really that helpful- we’ve added a layer of indirection but we’ve still got connascence of position, it’s just somewhere else now. This is where the Builder pattern comes in.

There we go- connascence of position has been removed and replaced with connascence of type. We can now send an alert without needing to know the order of the parameters to be passed. We have opened up other issues in the code though- for example, the way we’ve used the Builder pattern currently allows us to create an AlertRequest in an invalid state, which is far from desirable. If we’d used the pattern as intended, any required arguments would be part of the builder constructor… which would give us connascence of position again. Alternatively, we could throw an InvalidStateException when calling build() without first setting the required parameters.

You’ll also notice that we’ve replaced calling the JUnit library directly with calling a different library instead- AssertJ. This library uses fluent method chaining (A technique we’ve not looked at) to ensure connascence of position isn’t an issue.

Anyway, we’ll leave it to the audience to decide which technique to use and when it’s appropriate to use it. As always, there are tradeoffs to consider when changing any code- just do one that you’re comfortable with.

 

Connascence of Algorithm

Connascence of algorithm is the next level of connascence that we’re going to be looking at. We’re still in the static category of connascence, at level 4 (or 5, there seems to be some disagreement on the order of connascence of algorithm and connascence of position).

Connascence of algorithm is similar to connascence of meaning, though it tends to be more broad than agreeing on the meaning of one variable or value. Connascence of algorithm refers to when multiple components must agree on an algorithm used to perform a particular task- the obvious candidates for this are encoding, encrypting and decrypting, and hashing. There are also more subtle cases of connascence of algorithm, such as data validation.

Consider the following:

Wow. So much connascence of algorithm! Anyone would think it was an arbitrary example designed to prove a point…

Anyway, let’s take a closer look at the classes we have here. We have a Dinosaur that is created from DNA that has to be in a certain format. The dinosaur itself probably doesn’t care that much, but it makes it interesting for the other classes that rely on Dinosaur.

The DinosaurTransmitter and DinosaurReceiver are where the bulk of the connascence of algorithm lies. Our transmitter gets the plain DNA of the dinosaur and transforms the format into FASTQ for easier data transmission. We then encode the DNA into bytes with a Base64 encoder, using the bytes of the DNA in UTF-8 format. To ensure correct delivery of the entire payload, we’re also passing along an MD5 hash as a checksum.

And here lies our problem- The DinosaurReceiver is completely separate from the DinosaurTransmitter (Maybe even a different application completely), yet it has to know about each and every one of those algorithms- both individually, and the overall “transmission” algorithm, made up of all of those steps. We have to agree on using MD5 as the hashing algorithm for the checksum, we have to agree that the DNA is being sent Base64 encoded. We have to agree that the bytes being sent are UTF-8 encoded, and we have to agree that we’re using the FASTQ format to transmit the data, and the Dinosaur has to be created with plain format. If we change any of these encodings or hashing algorithms in one place, we have to change them in the other.

Another more subtle variation on connascence of algorithm is in data validation- where multiple software components must agree on the algorithm to use to ensure valid data. Let’s see what this might look like in action.

We’ve put safeguards in each of our application layers here, to make sure the name we’re assigning our dinosaur is valid. However, this has introduced connascence of algorithm- as if the validation algorithm ever changes in one place, it will have to change in all the others in order to remain correct and consistent across all layers.

Fortunately for us, connascence of algorithm can also be refactored into connascence of name in most cases. Let’s take our first example of transmitting a dinosaur. Consider the following changes:

We’ve extracted the majority of the connascence of algorithm into a DinosaurTransformer class, that the DinosaurTransmitter and DinosaurReceiver can refer to by name. The transformer still contains our connascence of algorithm in itself- the decode method must do the opposite of the encode method, but we’ve tried to extract as much of the algorithmic similarity into named concepts- both methods refer to exactly the same Charset, MessageDigest and DnaTransformer explicitly, reducing the connascence to connascence of name. The transmitter and receiver are now connascent with the DinosaurTransformer by name, but the connection they had with each other using the same algorithms in the same order is now broken. One must encode, the other must decode, and neither cares how it happens.

Our second example is more difficult to reduce the connascence- these are algorithms written in different languages for the same purpose, with no easy way of unification. And that’s probably ok- we eliminate as much connascence as we can given the constraints that we have, and remain conscious of the connascence that is left behind.

 

Connascence of Meaning

Connascence of meaning is the first type of connascence that we might want to do something about, rather than just being a natural part of programming itself. Connascence of meaning refers to when multiple components must agree on the meaning of values being used. Connascence of meaning is also called connascence of convention, as it can be better described as multiple components sharing a convention for the meaning of particular values. We’re going to use both of these terms throughout.

Consider the following classes:

These classes are coupled together by connascence of meaning- they both have to agree on the convention that using the number 1 for a dinosaur’s diet means carnivore, and 2 means herbivore. Presumably when they get some omnivorous dinosaurs, they’re going to have to agree that 3 means omnivore too.

A more common and insidious example of connascence of meaning in Java is agreeing on the meaning of null values.

Consider the following classes:

We’ve got a whole bunch of connascence of meaning over here around the meaning of null.

DinosaurEgg has some connascence over the meaning of timeLaid- all callers must agree with the convention of time laid referring to seconds. We also see our first example of the infamous “meaning of null”, where in this case null refers to the fact that the egg could not be hatched, because it wasn’t laid more than 10 minutes ago.

Our  DinosaurRegistry  uses a null return value when calling get() to indicate that the specified Dinosaur could not be found. Any callers must agree on the convention that null in this case means “dinosaur not found”.

DinosaurLab is the first place we experience this connascence of meaning across different components, as it has to interact with both DinosaurEgg and DinosaurRegistry, and as such has to agree on the convention of null. The DinosaurLab agrees on the meaning of null for the DinosaurRegistry, and does a null check on get() to make sure the specified name is not already registered for a Dinosaur (We don’t want a T-Rex and a Triceratops to both be called Bessie- what if you get confused when someone asks you to go give Bessie her medicine and wander off to the T-Rex enclosure? Not good things). The lab also has to agree on the convention of an egg returning null if it can’t be hatched, and checks whether the dinosaur returned from the egg is null or not.

You’ll notice that the DinosaurLab returns null in two different places, and for two different reasons. In the registry and the egg, null had one meaning and one cause. Not brilliant, but at least the calling classes only had to agree on the convention of null meaning one thing. In the lab, the null convention is used to convey that an egg could not be hatched- both because the egg is not ready to be hatched, and because the name is already registered. When our caller gets a null back from the lab- what do they do? Null means an egg couldn’t be hatched, but we have no idea why. Do we wait before trying again because the egg isn’t ready, or do we change it’s name because there’s already a T-Rex called Princess?

Fortunately, there are things we can do to reduce connascence of meaning into connascence of type and connascence of name.

For our first example, we can easily remove the convention of particular numbers meaning particular diets by introducing our own Diet type, we we can reference the diet of the dinosaur by name.

Consider the following change:

We’ve introduced a new enum Diet to describe the diet of our Dinosaur, and no longer have to rely on knowing that 1 = carnivore and 2 = herbivore, we’ve got it defined right there in the name and type. This is much better than relying on the implicit convention we were using before, as it’s much harder to mess up.

In our second example, the easiest way to remove the different conventions and meanings of null is to just not use null any more. Instead of using null to represent a negative case, we’re going to throw exceptions. We’re also going to introduce some new methods to call- so we don’t have to use the new exceptions we’re throwing to control the flow of our program.

Consider the following changes:

Our DinosaurEgg now throws an EggNotReadyToHatchException if the egg is not ready to hatch, instead of returning null. Now instead of callers relying on the meaning of null being “not ready to hatch”, they can rely on the name of the exception that is thrown, which reduces our connascence of meaning over the convention of null down to connascence of name- of the exception that is thrown. We’ve also made that isReadyToHatch() method public, as it allows us to not have to rely on try-catching an exception to control our program flow. We got rid of the ambiguity around timeLaid, and change it to be an explicit date. We also got rid of the implicit meaning of “600” being 10 minutes, by making it a named constant so we can more easily understand the meaning of the value.

DinosaurRegistry throws a DinosaurNotFoundException when using the get- as it shouldn’t be the usual case that calling get() doesn’t return a dinosaur. Now people won’t have to rely on knowing the meaning of a returned null, they can instead rely on the name of the exception that is thrown. We’ve put another method in place to check whether a name is available, again so we don’t have to rely on try-catch to control our program flow. We probably shouldn’t have been using that method for checking names in the first place, really.

Our DinosaurLab can now use our two modified classes, safe in the knowledge that the only things it now needs to care about is the names of the new methods to call, or alternatively the names of the new exceptions being thrown from the existing methods. We’ve also removed the conflated meaning of null being returned out of the lab, by introducing new exceptions for each individual reason for failure.

Connascence of meaning is the lowest level of connascence that we can realistically do something about- and even though it is such a low level, it doesn’t mean we should just let it be. The examples we used today were small, but if left to grow unchecked could grow to tangle up the whole codebase in collective understanding of the meaning of certain values- the problem becomes much worse when it’s a DinosaurHandler, ShippingContainer, FoodFactory, Dinosaur, DinosaurLab, DinosaurEnclosure, etc. that all rely on the convention of 1 meaning herbivore and 2 meaning carnivore… or was it the other way around?

Connascence of Type

Connascence of type is the second lowest level of connascence in the static category, just above name. Connascence of type refers to when multiple components must agree on the type of a particular entity. This can be the explicit type in a statically typed language like Java, where most type issues will be guaranteed to be correct by the compiler. It can also be the implicit type that’s expected in a dynamically types language like Javascript, where type issues will either cause runtime exceptions or just weird behaviour to occur. 

Consider the following classes:

Our classes have connascence of type, both in the class declaration and in the method declaration. If we try to get our DinosaurHandler to handle a Chicken instead, she’s not going to be very happy- our dinosaur handler is coupled to the Dinosaur based on it’s type. If we try to feed the dinosaur anything except Food- like say the dinosaur handler herself- things aren’t going to be pretty. Both of our components are dependent on being called and created with the correct types of objects.

Like connascence of name, you can’t really get rid of connascence of type either- we’re always going to have either:

A) an explicit contract stating we will only work on this type of thing, and don’t even try giving us anything else, or

B) an implicit contract stating that ok sure, give us anything but don’t expect us to work properly if it’s not what we’re expecting.

This is the reason connascence of type is only one level above connascence of name- types are an incredibly important aspect of programming and are inherent to the way that we program.

Connascence of Name

Connascence of name is the lowest level of connascence in the static category. Connascence of name refers to when multiple components must agree on the name of a particular entity. 

Consider the following class:

Our Dinosaur class has connascence of name- both for the class declaration and the method declaration. If we change the class from Dinosaur  to Chicken , anything that references the class by name will break. If we change the method name from feed()  to devour()  or anything else, anything that is using that method will break. All components that use Dinosaur  are dependent on the names that it uses.

You can’t get rid of connascence of name- it’s fundamental to the way we refer to different components and entities in programming. Whenever we change the name of a component in it’s declaration, we always have to change all code that refers to the old name. This is why we refer to connascence of name as the lowest level of connascence- it’s littered all over our codebases, and there’s not anything we can do about it.

Connascence

Connascence is a term used to describe the relationship and taxonomy of dependency between two software components. Connascence was used Meilir Page-Jones in the 90’s in the book What Every Programmer Should Know About Object Oriented Design (later updated to use UML instead of Page-Jones’s own modelling language in Fundamentals of Object-oriented Design in UML (Object Technology Series)) but has not seen widespread popularity in the development community outside of specific areas such as this talk by Jim Weirich and a series of blog posts and a talk by Kevin Rutherford.

Connascence provides a taxonomy for dependency and coupling, allowing developers to reason about the quality of their code. There are two broad categories of connascence, and 9 different types or levels. Connascence also has three properties which can help us decide how bad the particular level of connascence is.

But we have to know what connascence is first- how to spot it, how to classify it, and how to decide whether it actually is a problem or not given the level and properties of the connascence we’ve identified. 

That’s where this series of posts come in. We’re going to go over the different levels of connascence and how to spot them in the wild, as well as touch on the different properties of connascence to decide when we need to act.

We’re going to cover the following areas:

Static Connascence 

  • Connascence of Name
  • Connascence of Type
  • Connascence of Meaning
  • Connascence of Position
  • Connascence of Algorithm

Dynamic Connascence 

  • Connascence of Execution
  • Connascence of Timing
  • Connascence of Value
  • Connascence of Identity

Properties of Connascence

  • Strength
  • Locality
  • Degree