6 days Ago
Hard drives => SSDs
In the old days, we cleaned up our hard drives because we didn’t have enough space for all of our stuff. Our operating systems, applications and caches took up a reasonable portion of that hard drive.
Then we had gigantic hard drives with more than enough space for everything. Operating systems, applications and caches grew. Parsimonious software was no longer in vogue because it was a waste of time and money.
SSDs replaced hard drives, improving speeds drastically and ushering in a new era in performance. This did not come without cost, though. SSDs were much more expensive to make, so the affordable ones were necessarily much smaller than our existing hard drives. Our operating systems, applications and caches have not made the adjustment, though, at least not on Windows.
We are left with drives 70-80% smaller than the ones we had a couple of years ago—256MB vs. 1TB. Developers, in particular, tend to have software that uses space indiscriminately.
Drive space: critical
I recently noticed that my system drive had filled up to almost 80% and took a little time to do something about it. I downloaded TreeSize Free from Jam Software to get an idea of which folders took up the most space. I also referred to Guide to Freeing up Disk Space under Windows 8.1 by Scott Hanselman: there are a lot of great tips in there.
Without further ado, here are the locations that struck me as being “space hogs”—locations that were large but didn’t seem to offer much utility or seemed to be logs, caches or backups.
- This folder is almost 22GB on my machine. It seems to contain MS installers, updates, service packs and hot-fixes. There are a few tips online—some from Microsoft—on how to clean up this folder. Even after running a couple of them, I didn’t notice a significant difference in size. I didn’t spend a lot of time here, but cleaning up this folder would yield significant savings.
- SQL Server
- There were several gigabytes—I had 2.8GB—of older versions and installers in the main SQL Server folder, located at
/Program Files/Microsoft SQL Server/110/Setup Bootstrap. If you have large databases, consider moving them to another drive or location and setting the default data directory to somewhere other than the Program Files directory on the system drive.
- I use this player for podcasts. It stores almost 1GB in something called the “icon cache”, located at
/Users/<username>/Roaming/Participatory Culture Foundation/Miro/icon-cache
- SmartGit updates itself automatically now and they have very regular builds and updates, especially if you use preview releases. It never seems to delete these updates, instead retaining them in
I use this to keep track of my day, referring to it to fill out my timesheet. Screen captures are located in
/Users/<username>/Local/TimeSnapper/Snapshots. The default settings are to capture 100%-quality PNG files for all monitors every ten seconds. I have two large monitors and the default 5GB cache fills up in less than a day. This is not very helpful and wastes a lot of space. Instead, I recommend these settings:
- File Type: JPG
- Resolution: 50%
- Quality: 50%
- Interval: 60 seconds
- Remove images older than: (not set)
- Maximum allowed space: 1000MB
- If you build XML documentation locally, you might have a sizable cache left over from the last build. I had over 800MB in the
\Users\<username>\AppData\Local\EWSoftware\Sandcastle Help File Builder\Cache
- Java also likes to update itself regularly and never throws away its older versions. Unless you know that you absolutely need a specific version, you can throw away the older versions found in
- The Visual Studio documentation extension keeps quite an extensive cache in the
- This is another company that squirrels away all of its installers for its various products—I use DotPeek, DotCover, DotTrace, ReSharper, PhpStorm and 0xDBE—in this folder
\Users\marco\AppData\Local\JetBrains. Feel free to throw away old installations and installers.
- This mysterious folder located at the root of the system drive has been around since time immemorial. It appears to be 0 bytes when examined with a standard user. When you run TreeSize in administrator mode, though, you’ll see that it’s 2.4GB of … stuff. This stuff is apparently installers for all of the office products that you have installed on your machine. They are cached in this folder in order to avoid requesting installation media if Office decides to install something on-the-fly. That’s right: if you elect not to install certain features to avoid wasting drive space, Office obliges by putting all of the stuff you didn’t install into a 2.5GB directory that you can’t delete. Documentation is spotty, but this article claims that you can remove it by using the standard disk-cleanup tool.
This list is meant to show where space is being wasted on a Windows developer machine. I wasn’t able to find a way to remove all of these, but cleaned up what I could quickly clean up.
If you’re really tight on space, you can turn off hibernation—which uses 13GB on my machine—or reduce the size of the page file—which is 6GB on my machine. And, as mentioned above, Scott Hanselman’s guide is quite helpful.
2 weeks Ago
In the previous article, I explained how we were using NDepend to clean up dependencies and the architecture of our Quino framework. You have to start somewhere, so I started with the two base assemblies: Quino and Encodo. Encodo only has dependencies on standard .NET assemblies, so let’s start with that one.
The first step in cleaning up the Encodo assembly is to remove dependencies on the Tools namespace. There seems to be some confusion as to what belongs in the Core namespace versus what belongs in the Tools namespace.
There are too many low-level classes and helpers in the Tools namespace. Just as a few examples, I moved the following classes from Tools to Core:
The names kind of speak for themselves: these classes clearly belong in a core component and not in a general collection of tools.
Now, how did I decide which elements to move to core? NDepend helped me visualize which classes are interdependent.
We see that
EnumerableTools depends on
StringTools. I’d just moved
Encodo.Core to reduce dependence on
Encodo.Tools. However, since
StringTools is still in the
Tools namespace, the dependency remains. This is how examining dependencies really helps clarify a design: it’s now totally obvious that something as low-level as
StringTools belongs in the
Encodo.Core namespace and not in the
Encodo.Tools namespace, which has everything but the kitchen sink in it.
Another example in the same vein is shown to the left, where we examine the dependencies of
Encodo.Tools. The diagram explains that the colors correspond to the two dependency directions.
We would like the
Encodo.Messages namespace to be independent of the
Encodo.Tools namespace, so we have to consider either (A) removing the references to
MessageTools or (B) moving those two dependencies to the
Choice (A) is unlikely while choice (B) beckons with the same logic as the example above: it’s now obvious that tools like
OperatingSystemTools belong in
Encodo.Core rather than the kitchen-sink namespace.
Once you’re done cleaning up your direct dependencies, you still can’t just sit back on your laurels. Now, you’re ready to get started looking at indirect dependencies. These are dependencies that involve more than just two namespaces that use each other directly. NDepend displays these as red bounding blocks. The documentation indicates that these are probably good component boundaries, assuming that the dependencies are architecturally valid.
NDepend can only show you information about your code but can’t actually make the decisions for you. As we saw above, if you have what appear to be strange or unwanted dependencies, you have to decide how to fix them. In the cases above, it was obvious that certain code was just in the wrong namespace. In other cases, it may simply be a few bits of code are defined at too low a level.
Improper use of namespaces
For example, our standard practice for components is to put high-level concepts for the component at the
Encodo.<ComponentName> namespace. Then we would use those elements from sub-namespaces, like
Encodo.<ComponentName>.Utils. However, we also ended up placing types that then used that sub-namespace in the upper-level namespace, like
ComponentNameTools.SetUpEnvironment() or something like that. The call to
SetUpEnvironment() references the
Utils namespace which, in turn,
references the root namespace. This is a direct dependency, but if another namespace comes between, we have an indirect dependency.
This happens quite quickly for larger components, like
The screenshots below show a high-level snapshot of the indirect dependencies in the Encodo assembly and then also a detail view, with all sub-namespaces expanded. The detail view is much larger but shows you much more information about the exact nature of the cycle. When you select a red bounding box, another panel shows the full details and exact nature of the dependency.
Base Camp Two: base library almost cleaned up
- ICoreConfiguration: references configuration options for optional subsystems like the software updater, the login, the incident reporter and more
- ICoreFeedback: references feedbacks for several optional processes, like software-update, logins and more
- ICoreApplication: references both the core configuration and feedback
The white books for NDepend claim that “[t]echnically speaking, the task of merging the source code of several assemblies into one is a relatively light one that takes just a few hours.” However, this assumes that the code has already been properly separated into non-interdependent namespaces that correspond to components. These components can then relatively easily be extracted to separate assemblies.
The issue that I have above with the Encodo assembly is a thornier one: the interfaces themselves embody a pattern that is inherently non-decoupling. I need to change how the configuration and feedback work completely in order to decouple this code.
Roadmap for startup and configuration
To that end, I’ve created an issue in the issue-tracker for Quino, QNO-4659, titled “Re-examine how the configuration, feedback and application work together”. The design of these components predates our introduction of a service locator, which means it’s much more tightly coupled (as you can see above).
After some internal discussion, we’ve decided to change the design of the Encodo and Quino library support for application-level configuration and state.
- Merge the configuration and application
- To date, the configuration has contained all of the information necessary to run an application. The configuration was more-or-less stateless and corresponded to the definition of an application, akin to how a class is the underlying stateless definition, while an object is an instance of that definition. In practice, though, we always use a single application per configuration and the distinction is irrelevant, for all practical purposes. This will simplify all referencing code, as we will no longer need to pass around an
- Move the feedback to the service locator
- Instead of treating the feedback like a first-class citizen, with a direct reference on the application, make consumers use the service locator to retrieve an instance. This will remove the remaining generic argument in the definition of
IApplication, leaving us with a base interface that is free of generic arguments.
- Move specific configuration objects to the service locator
- The specific sub-interfaces that introduce dependencies are as follows:
Any components that currently reference the properties on the
ICoreConfigurationcan use the service locator to retrieve an instance instead.
- Move specific settings to sub-objects
- The configuration object is not only dependent on sub-objects, but is also overloaded with individual settings that are only used by very few specific sub-components. These will also be extracted into interfaces and moved into the service locator.
As you can see, while NDepend is indispensable for finding dependencies, it can—along with a good refactoring tool (we use ReSharper)—really only help you clean up the low-hanging fruit. While I started out trying to split assemblies, I’ve now been side-tracked into cleaning up an older and less–well-designed component—and that’s a very good thing.
There are some gnarly knots that will feel nearly unsolvable—but with a good amount of planning, those can be re-designed as well. As I mentioned in the previous article, though, we can do so only because we’re making a clean break from the 1.x version of Quino instead of trying to maintain backward compatibility.
It’s worth it, though: the new design already looks much cleaner and is much more easily explained to new developers. Once that rewrite is finished, the Encodo assembly should be clean and I’ll use NDepend to find good places to split up that rather large assembly into sensible sub-assemblies.
Bare interdependent, but
Ashould not rely on
B, you should make sure
Ais showing in the column. You can then examine dependencies on row
B—and then remove them. This works very nicely with both direct and indirect dependencies.↩
I received the post Maine Just Changed Their Food-Stamp Policy… Every State Should Do This (Conservative Tribune) from a friend.
The friend wondered whether the following was a good idea. They thought it might be, but asked if I could confirm.
“[…] adults 18 to 50 years old with no children and who are able to work must do so or volunteer for 20 hours each week. Otherwise, their benefits will be limited to three months over a three-year period”
This is one of those superficially seductive ideas that keeps coming up. Basically, should the U.S. privatize and marketize the remaining social components of its safety net? Should it remove the last vestiges of mercy from its society?
They are not us
This idea assumes that people on welfare are lazy. That their inability to support themselves and their families and subsequent desperation is purely their own fault. That they deserve their fate.
But—and I think this is the most important part of all—if we believe that those on welfare deserve to be treated poorly, then those of us not on welfare are free to believe that we earned our much better lives.
There is no mercy in such a system, no acknowledgment that the system treats some much worse than others. That luck plays a large role in the lives of both the most disadvantaged and the most advantaged.
There are so many factors dooming people to poverty in America. Programs like this, that force their participants to dance for their supper, are a cruel joke. They make those of us who will never have to be part of one of these programs feel vindicated, but that feeling comes from a petty, stupid and cruel place.
Lazy. Stupid. Ignorant.
Given this presupposition, it of course makes sense to punish others for being poor, to extract what we can from them instead of supporting these parasites.
There are so many reasons other than laziness that people can’t get jobs:
- There aren’t enough jobs that pay living wages
- The jobs that are available are soul-killing or physically dangerous
- The education system is a joke; There is no training for good jobs
- The continuing education system is weak to nonexistent
- Many “decent” jobs are out of reach for anyone without at least a bachelor’s degree
- There is prejudice everywhere against the poor
- Don’t have nice clothes? Forget office work
- Can’t speak without an accent? Or slang? Forget office work
- Bad teeth? Forget a whole slew of jobs
- Not pretty? Overweight? Same thing.
- Black? Hispanic?
Tantamount to slavery
Instead of giving the poor help to get them back on their feet, we give them what amount to jobs. I suppose this sounds good to some. There’s a lot of work to do and not enough people to do it.
If they don’t comply, they no longer get the benefit of the doubt. If they don’t comply, they get their super-generous benefits of a few hundred dollars per month for only three months and then nothing for thirty-three more months.
If you can’t find a job of your own—or are unwilling to do so—you have to do the job you’re given by the state. This is just a transformation of the unemployment program, though. Instead of making you seek out jobs in your area of expertise, these new programs just give you a job.
And what do you get paid for this job? The article says “or volunteer 20 hours each week”. If you have to do the work to get benefits, then it is, by definition, not volunteering. But what they mean by “volunteer” is that you’re doing the job for no salary, other than the benefits (which you used to get for free).
Welfare benefits are notoriously meager. Most recipients are scraping the bottom of the barrel by the third week of the month, no matter how well they stretch them. This is not a luxurious lifestyle.
So, even if you do get paid for your work, the salary is almost certainly far below minimum wage.
Life in the hands of the state
Under such a system, people will have a job of sorts, but far less chance to get control back over their lives.
If you spend 20 hours per week working at this shitty, super-low-paid job, do you have time to find a better one? No, you probably do not. Do you have time for your continuing education program? No to that too. What about your kids? Who takes care of them while you work? Hire a babysitter. It’s good for the economy.
It’s hard to imagine that society that converts its welfare program to something like this will pay a living wage. And you can forget about benefits or any thought for how a life is supposed to work under this regime. That’s not the taxpayer’s problem because they’re already being generous enough by throwing a few dollars and a job the recipient’s way.
Don’t like it? Don’t take the extravagant benefits, you lazy bastard.
And stop whining about your kids.
You shouldn’t have had them if you can’t take care of them.
And your kids are future freeloaders.
Race to the bottom
These programs are not new. Back in the 90s, the “workfare” program was the brainchild of Bill Clinton (yep, the so-called progressive). Mayor Rudolph Guiliani implemented it in NYC by making welfare recipients work in the park system.
What happened? Their salaries were on the order of a dollar or two per hour and so they were much cheaper to hire than the current park staff. The current staff was let go and replaced with much–lower-paid unskilled labor. A win all around, right? The skilled and trained labor lost their good jobs.
Taxpayers win because they also don’t have to pay for benefits or pensions or anything. Awesome, right? Because nobody who mattered knew anyone with a good job in the park system, so the park workers might as well not even exist.
So what happens with all of those people who just lost their jobs? No problem. They go on welfare and can go right back to work in the park, but at 1/10 of their former salary without benefits or a pension. Sweet.
This kind of program gets rid of good jobs and makes everyone race to the bottom, working harder for less. It’s capitalism at its finest.
No more unions, no more pensions, no more benefits. Not for the poor. They don’t deserve it. If they did, wouldn’t they already have it?
Being poor is not a crime
The problem with this workfare kind of thinking is that it demonizes those out of work or down on their luck. It takes the few that are really lazy, makes anecdotes out of them to convince people that everyone is like that, and then making slaves out of them, more or less.
You can’t say, as the governor of Maine did, that you’re doing “all that you can to eliminate generational poverty and get people back to work” if you haven’t actually created real jobs and real job training. If the only jobs around are life-draining and crappy—and you have to get two of them to survive—are we surprised that people don’t want to do them?
Do some take advantage? Sure, they do. Do we doom the majority that actually need welfare programs and could benefit from them just to punish the few that ruin it for everyone? Do we have to do it? Is it that we can’t afford it? Or that we spend money on everything but the poor?
This program will drive people off of welfare—not because they don’t want to work, but because they don’t want to get trapped into the forced-work program of the state. They want dignity and control over their own lives, even though they’re poor. Can’t we afford to give them that?
There’s no money in helping people
If we need to spend billions and trillions to deploy to Iraq or to build the next generation of super-weapons or to start giant new agencies—like Homeland Security and the TSA—ostensibly to fight terrorism, no one says a thing.
Spend a few millions on the poor without them somehow paying us back and we’re up in arms.
We have no sense of proportion. We are not very nice.
And we are cruel to those less fortunate. Because ill fortune is mostly why people are poor: they aren’t lucky enough to have been rewarded for the right behavior. Life has taught them that it’s not even worth trying anymore. They’re not necessarily inherently stupid or lazy; they have just learned the lesson that their lives taught them.
We continue to try because our experience has trained us that if we work hard, we achieve. How many years would you continue to work hard if you never achieved? If you were never rewarded, not even once? If life swatted you down? Every. Single. Time. Would you really keep getting back up?
Would you work as hard as you do if you were paid $150 a week after taxes? Would you keep looking for that job with the same energy after the first year of joblessness? At what point do you say “yes” to something criminal just to get some cash to feed yourself or your family?
And then you’re going to jail. Because you’re a criminal and deserve it. Because being poor pretty much is a crime.
Standing in judgment
We find it so easy to judge people about whom we know nothing. And it’s easy to lump all the poor together because most of us don’t know any of them or don’t have to sympathize with them. Or we hear stories about them from TV. Stories written by people who also probably don’t know any poor people. Or from cops, who have an adversarial relationship to them, granted them by the state. It goes on and on.
We don’t know them but we feel perfectly comfortable judging them. Only a society without empathy could make a so-called welfare system life this.
“What do you think of Obama?”
He is Barack Hussein Obama,
44th—and first black—President of the United States of America.
Nobel Peace-prize winner.
So-called leader of the free world.
The Drone Ranger.
Mr. extraordinary rendition.
The whistle-blower hunter.
Defender of the 0.1%.
The question above is posed in different ways, in different tones. It depends on the person posing it. If the person hates Obama—for any of a variety of reasons, into which I may go later, then the question is accompanied by a conspiratorial leer. The leer extends a hopeful olive branch, anticipating an enjoyable evening of exchanging highly questionable information about Obama and his purported policies.
If the person likes Obama, they usually hope that you don’t mention torture, the financial bailout, drones, Guantánamo, Israel or any of another host of issues on which Obama is decidedly not progressive. Even the ACA—called “Obamacare” by nearly everyone—which he would likely deem to be the major part of his legacy, crumples under more progressive scrutiny.
Heaven forfend you mention any of Obama’s campaign promises—from 2008 or 2012—because his failure to have accomplished any of them in the manner he’d promised is—according to these people—most definitely not his fault. It is the fault of the Republicans.
So, his detractors oppose everything he stands for and his supporters acknowledge that he sucks but it’s not his fault.
Whose fault is it then?
The short answer? The system sucks and good luck changing it.
That many high-ranking Republicans seem hell-bent on policies that benefit only themselves and their friends to the detriment of all others is abundantly clear. That this group also includes many Democrats is also clear. Just because only 93% of Democrats are assholes versus 95% of Republicans doesn’t make much difference to the casual observer. The natural conclusion to which to come is that they’re all assholes and you won’t be off by much. Assuming this will equip you well for dealing with them all. At the least, not trusting any of them is a good start. But I digress.
Of course, if their policies benefit you, then you’ll think they’re a swell bunch of guys—and they are still, mostly, guys. But you’re in a small minority. The vast majority of people in the U.S. and the world have nearly nothing in common with their representatives, be they in the U.S. or Iran or Russia or China … or any of dozens of other countries that happily count themselves in the OECD. There are a few where the government seems to work for the people instead of the other way around—e.g. Switzerland and a handful of Scandinavian countries, perhaps—but not many of us are lucky enough to live there.
The U.S.. is definitely in the other category, where the people pretty much work for the government, but let’s not forget: the government, in turn, works for its own masters. But those masters are not us.
Corporations are people, in the U.S. at least. Those are the real masters of the 21st century. It is they—and their ultra-exclusive owners—who wield the real power. They call themselves the masters of the universe and have yet to be proven wrong.
Obama: smart? dumb? a dupe? evil?
Which brings us back to Obama. He’s incredibly far removed from any one of us. He can very eloquently express viewpoints that sound as if they sympathize and even echo our own. But he’s lying. We’ll leave it to history to decide for sure whether he himself knows he’s lying—but I’m going to come out and write that anyone that smart is at least self-aware enough to know that what he says and what he does almost never line up.
I’m sure it’s frustrating to constantly have to say things that you don’t mean in order to get things done that you really want. Such is the life of a politician. It’s not easy convincing people to do things against their own best interests—or against basic morality. Which is why you have to lie to them so much.
Is Obama a dupe? No, I don’t think so. That’s giving him too much credit. It’s so easy to buy the story that he’s desperately trying to enact a progressive program in America while presiding over one of the greatest regressive swings in history. Do people think that he’s the Mr. Magoo of politics? That he accidentally swings the economy in the favor of the bankers and Wall Street while really, honestly and desperately trying to do the right thing for the vast majority of Americans? How bloody hopeful and simple-minded could you possibly be to believe that? Believing this fairy tale ensures only that Obama—or someone very much like him—will hoodwink you again.
It’s the system, stupid
But we can substitute the name “Obama” with the name of any politician. I want to emphasize that I don’t think he’s special, or especially bad. He’s just the current president. He’s the same—more or less and for all practical purposes—as all the rest. He starts wars, he runs a drone-based, extra-judicial assassination program that is demonstrably criminal and evil, he lowers taxes, he gives gobs of money to large corporations (hello, health-insurance industry), he glorifies the military and showers it with endless cash and weapons programs, he allows torture while redefining it otherwise semantically, he embargoes and fights economic wars against helpless nations, he ignores climate change, expands fossil-fuel subsidies and he promulgates an arrogant trade program that is a finger in the eye of every nation in the world.
It goes on and on. Business as usual. What the hell is so different about this model versus the last one, objectively speaking?
Why hate Obama? Many seem to hate him because he is black. This can be the only reason because it’s literally the only thing that they objectively don’t like about him. This single reason is overwhelmingly influential in how people form an opinion of him that they ignore a veritable slew of reasons that they should like him, all political and policy-oriented in nature. Reasons that should, by all rights, be much more important to a person than his skin color, but there you have it—man is a frail creature and a fallen one.
Anti-progressives should love Obama
Yes, they should! He’s done absolutely everything he could to make them love him.
Bankers like Obama; he does everything they like. Republicans hate him, but he does almost everything like a Republican. He funnels tons of cash to the richest in our land and neglects everything that would benefit the poor. During his entire administration (and part of Bush’s) all of the income increase has been captured by the top 1%. Everyone else went backward. Is this the mark of a progressive? Only in a country as broken as the U.S., perhaps.
Even the ACA is a sop to insurance companies—the far more progressive single-payer model was swept off the table by the Obama administration even before negotiations started. People don’t remember that he didn’t even fight for it; he never wanted it.
Obama has the sweetest gig in politics: everything he wants, the Republicans want the exact opposite with a religious zeal. So he can say he wants the most outlandishly progressive things and he is nearly assured that the Republicans will deliver America the exact opposite. He looks like he’s trying to save humanity, and the Republicans deliver the regressive program he actually wanted.
Support is opposition; war is peace;
His recent support of net neutrality is a good example. What are the odds that the Internet will be regulated as a utility with the Republicans in charge for the next two years? Vanishingly small. What are the odds that it will happen if Obama wants it to happen? Zero percent.
The exact same goes for the much-ballyhooed climate agreement with China. More smoke and mirrors that looks progressive, but is all about meeting voluntary targets. China will probably actually meet theirs. The U.S.? With a Republican-controlled Congress and Senate? Not a fucking chance by Peter Lee (CounterPunch). But Obama gets the progressive praise for “trying”.
So why does Obama support these things now, when he was all wishy-washy about it before? Hard to say.
I would like to think that it’s because Obama has found a backbone and realized that he has nothing to lose by finally standing up for what he believes in. I’ve always said that he should have been doing exactly that, that he could at least stand for what he believes in rather than compromising all the time and getting nothing out of it.
But if you have a hint of cynicism in you, you’ll be gut-laughing at my naiveté right now. Hell, I’m laughing at me for even having written it. This is the story that Obama is selling. Do not buy it.
I think that it’s much more likely that this is yet another example of something that Obama doesn’t really believe in but that he thinks he has to say in order to seal his legacy as a progressive president—because history has little do with reality, and American history even less so.
Or maybe he really is just manipulating the Republicans into doing what they all really want: the further privatization of America and the world, the promulgation of the single-minded and simplistic breed of capitalism that we seem to be stuck with.
Is he ineffective because he’s stupid? Or too smart? Too principled? His opposition is too evil? Is he actually effective?
Who knows? Who cares?
How many more years do we have to waste thinking about this?
What matters is that he is not part of the solution for the real problems that we have. That’s all you need to know, I think.
A while back—this last spring, I believe—I downloaded NDepend to analyze code dependencies. The trial license is fourteen days; needless to say, I got only one afternoon in before I was distracted by other duties. That was enough, however, to convince me that it was worth the $375 to continue to clean up Quino with NDepend.
I decided to wait until I had more time before opening my wallet. In the meantime, however, Patrick Smacchia of NDepend approached me with a free license if I would write about my experiences using NDepend on Encodo’s blog. I’m happy to write about how I used the tool and what I think it does and doesn’t do.
History & Background
Fast-forward seven years and Version 1.13 of Quino has 66 projects/assemblies. That’s a lot of code and it was long past time to take a look a more structured look at how we’d managed the architecture over the years.
I’d already opened a branch in our Quino repository called feature/dependencyChanges and checked in some changes at the beginning of July. Those changes had come as a result of the first time I used NDepend to find a bunch of code that was in the wrong namespace or the wrong assembly, architecturally speaking.
Sidebar: Keeping branches mergeable
I wasn’t able to continue using this branch, though, for the following reasons.
- I got the hang of NDepend relatively quickly and got a bit carried away. Using ReSharper, I was able to make a lot of changes and fixes in a relatively short amount of time.
- I checked in all of these changes in one giant commit.
- I did this all five months ago.
- There have been hundreds of subsequent commits on the master branch, many of which also include global refactoring and cleanup.
- As a result of the above, merging master into feature/dependencyChanges is more trouble than it’s worth.
With each Quino change and release, we try our hardest to balance backward-compatibility with maintainability and effort. If it’s easy enough to keep old functionality under an old name or interface, we do so.
We mark members and types obsolete so that users are given a warning in the compiler but can continue using the old code until they have time to upgrade. These obsolete members are removed in the next major or minor upgrade.
Developers who have not removed their references to obsolete members will at this point be greeted with compiler errors. In all cases, the user can find out from Quino’s release notes how they should fix a warning or error.
The type of high-level changes that we have planned necessitate that we make a major version-upgrade, to Quino 2.0. In this version, we have decided not to maintain backward-compatibility in the code with
Obsolete attributes. However, where we do make a breaking change—either by moving code to new or different assemblies or by changing namespaces—we want to maintain a usable change-log for customers who make the upgrade. The giant commit that I’d made previously was not a good start.
Since some of these changes will be quite drastic departures in structure, we want to come up with a plan to make merging from the master branch to the feature/dependencyChanges branch safer, quicker and all-around easier.
I want to include many of the changes I started in the feature/dependencyChanges branch, but would like to re-apply those changes in the following manner:
- Split the giant commit into several individual commits, each of which encapsulates exactly one change; smaller commits are much easier to merge
- Document breaking changes in the release notes for Quino 2.0
- Blog about/document the process of using NDepend to clean up Quino
So, now that I’m ready to start cleaning up Quino for version 2.0, I’ll re-apply the changes from the giant commit, but in smaller commits. At the same time, I’ll use NDepend to find the architectural breaks that caused me to make those changes in the first place and document a bit of that process.
Setting up the NDepend Project
I created an NDepend project and attached it to my solution. Version 1.13 of Quino has 66 projects/assemblies, of which I chose the following “core” assemblies to analyze.
I can change this list at any time. There are a few ways to add assemblies. Unfortunately, the option to “Add Assemblies from VS Solution(s)” showed only 28 of the 66 projects in the Quino solution. I was unable to determine the logic that led to the other 38 projects not being shown. When I did select the projects I wanted from the list, the assemblies were loaded from unexpected directories. For example, it added a bunch of core assemblies (e.g. Encodo.Imaging) from the
src/tools/Quino.CodeGenerator/bin/ folder rather than the
src/libraries/Encodo.Imaging/bin folder. I ended up just taking the references I was offered by NDepend and added references to
Quino, which it had not offered to add.
The NDepend Dashboard
Let’s take a look at the initial NDepend Dashboard.
There’s a lot of detail here. The initial impression of NDepend can be a bit overwhelming, I supposed, but you have to remember the sheer amount of interdependent data that it shows. As you can see on the dashboard, not only are there a ton of metrics, but those metrics are also tracked on a time-axis. I only have one measurement so far.
Any assemblies not included in the NDepend project are considered to be “third-party” assemblies, so you can see external dependencies differently than internal ones. There is also support for importing test-coverage data, but I haven’t tried that yet.
There are a ton of measurements in there, some of which interest me and others that don’t, or with which I disagree. For example, over 1400 warnings are in the Quino* assemblies because the base namespace—Encodo.Quino—doesn’t correspond to a file-system folder—it expects Encodo/Quino, but we use just Quino.
Another 200 warnings are to “Avoid public methods not publicly visible”, which generally means that we’ve declared public methods on internal, protected or private classes. The blog post Internal or public? by Eric Lippert (Fabulous adventures in coding) covered this adequately and came to the same conclusion that we have: you actually should make methods public if they are public within their scope.
There are some White Books about namespace and assembly dependencies that are worth reading if you’re going to get serious about dependencies. There’s a tip in there about turning off “Copy Local” on referenced assemblies to drastically increase compilation speed that we’re going to look into.
Dependencies and cycles
One of the white books explains how to use namespaces for components and how to “levelize” an architecture. This means that the dependency graph is acyclic—that there are no dependency cycles and that there are certainly no direct interdependencies. The initial graphs from the Encodo and Quino libraries show that we have our work cut out for us.
The first matrix shows the high-level view of dependencies in the Encodo and Quino namespaces. Click the second and third to see some initial dependency issues within the Encodo and Quino assemblies.
That’s as far as I’ve gotten so far. Tune in next time for a look at how we managed to fix some of these dependency issues and how we use NDepend to track improvement over time.