Recently I’ve been working with WPF on my first medium-or-large development project. Am I allowed to acknowledge that I don’t have seven thousand-plus (7000+) of these big apps already under my belt, career-wise? I guess i just did. Anyway, it’s been fascinating. All these principles that you read about and that sound nice, but aren’t causing you pain in your 400LOC web part project, become ugly quickly on a large, connected codebase. I’ve now had the time to experience the following concepts personally. Notably:
- The DRY principle, and how duplication in your code creates bugs. I think I’ve seen someone with more authority say this elsewhere, but, let me pretend to be the first to say it: if you only focus on one thing to improve in your codebase, start with removing duplication. Removing duplication has been eye-opening for me. Once you remove all the duplication, then you can worry about restructuring the code, but not until you’ve removed the duplication.
- Allowing broken windows to remain broken leads to a downward spiral of code quality. This is one of the opening sections of the Pragmatic Programmer book.
- The need for unit testing to ensure specific behaviors work as designed, and to help you express intent, and to ensure that the code remains working down the line, when everyone has forgotten what the code is supposed to do. Tests also break a lot (we’re working on making them more unit-ish).
- Integration testing and how, in conjunction with unit tests, it helps ensure your system works, and allows large-scale restructurings (and allows dangerous merges using the team suite source control product from the unnamed vendor).
- The importance of continuous integration (and as much as possible, continuous deployment) as a means of chaos control on a team project. “Who broke the build” actually matters on a team. If you ask “who broke the build” on your one-man project, you get funny looks because you’re mumbling to yourself again.
- SOLID (particularly the Liskov substitution principle) and how it leads to more readable/easily-digestible/composable code.
- Object modeling and carefully selecting object responsibilities (which ties into SOLID) and how drastically a seemingly-small change in the responsibilities of objects drastically changes the way your code works and looks. I’m still struggling with choosing the right seams between object responsibilities.
- BDD or STDD or ATDD or whatever you’re calling it – honestly we’re not doing anything like this on our project, but I’m feeling the pain nonetheless. Part of the problem is that Agile is hard to do 100% well, and part of doing a good job is putting away the pride and not doing Agile 100% well in order to get the job done. I may sound like a luddite here, and I’m sorry, but the truth remains: if we have a skill gap between the ideal Agile team, and us, and we need to deliver, we work at our current skill level. No regrets. …Back to BDD. Another part of the problem is that BDD (and unit testing) get into this fuzzy area where it’s difficult for the unskilled practitioner (read: me) to follow a rigid set of rules that will get me to the land of BDD goodness, where our customers tell us a story of just the right size with just the right level of detail, and we take those very same words and create a behavior test, and that behavior test is written with just the write level of granularity, and it’s all effortless and the tooling is excellent and we review all the behaviors as a team, and lo and behold! The customer spots a design bug just by reading the names of our behavior tests, and we’ve saved 5000 man hours because we caught it before it was implemented. I’m still not there. And neither is the team of which I’m a member.
- Technologies are still frustrating, but not on the same level. I’ve had to implement one (1) ugly workaround involving a WPF data grid, and while it was unsavory, at least it wasn’t a complete brick wall. It’s kind of funny how the grizzled veteran SP developer within me jumps to create an ugly workaround that gets the job done, instantly, without a moment of hesitation or regret. My lead asked me, “are you sure there’s not a way to fix the problem properly?” Because most people are trained to solve the problem, the right way. Nope, I’ll just do an ugly workaround and move on.
- LightSpeed ORM works, but I have two major complaints:
- One: we are forced to inherit from a base class. This means that we have to carry the LightSpeed DLL into every project in which our model objects are used (hint: all of them). Also, arising from LightSpeed’s ID column magic in the base class, is the problem that you can’t set an entity’s ID field for unit tests without even deeper magic. It’s an ID column, I want to set it so I can test equality, without ugly hacks or counterspells to counter the LightSpeed magic.
- Two: (and perhaps more importantly) using LightSpeed means that we can’t use interfaces in our model. [removed 300 word attempt to summarize the problem. Take my word for it, we can’t do it easily, and we want to. Included in the 300 words I deleted is the phrase “by jove,” which I think needs to get more playtime. -ed] This is probably also why the POCO (plain old C# objects) crowd is so militant about POCO itself—this whole business about using a base class and relying on attributes to do relationship mapping gets ugly in a hurry. Composability again—it’s important.
- Three: some of the features are buggy. it’s hard to say how much of the bugginess is our misuse (PEBKAC error) or our unique scenario, but bugs kill productivity and sap energy. I wish we had NHibernate instead of this paid product, and would not be dismayed if we moved to the Entity Framework v37 or whatever number is assigned for this year’s release.
- MVVM is much better than not having MVVM. I’ve seen code that uses the codebehind approach when an MVVM approach would have worked, and the MVVM code is SO MUCH EASIER (!!!)!!)!(!)!)!(!(!) to figure out and modify. Craziness. Small note: once I’m beyond the remedial MVVM stage, I need to venture out and see what other presentation models exist. Later. Not now.
- I’m sure we could be doing MVVM better, but it’s a small fry issue in the grand scheme of things. It’s not the root cause of any of our pain, though I’m nervous about holding child viewmodels, and then children of the child viewmodels, and so on. Also don’t ask us whether we’re viewmodel-first or view-first, we’re more a federation of fiercely independent states, like the united federation of planets, only with views and viewmodels. We are unique and we make our own decisions, and you can make your own decisions. Vulcans are strictly ViewModel-first.
- The Prism event aggregator is just beautiful. Maybe I’m biased, because I’m comparing it to not using an event aggregator at all, and attempting to cobble together an event notification solution using property change notifications on child and (great?)-grandchild-viewmodels. I assure you the previous sentence gives me NIGHT TERRORS just thinking about it. Trust me on this. It’s like trying to follow code written by Macguyver—clever, and gets the work done, but cobbled together with bailing wire, a bar of soap, and a lit cigar. I should make a law out of this: You Don’t Want To Maintain Macguyver’s Codebase. Peter’s Law #59 ©2010, All Rights Reserved, ®, TM, Patent Pending.
- Unity is a problem, because it doesn’t allow us to pass parameters into the constructor at runtime (think data) while injecting the rest of the dependencies (think services). I’m somewhat new to the fanciness of IoC tools, but I’m pretty sure on this—the other tools allow you to do what I’m asking. Unity DOES allow us to work around the problem but…without going into a long boring exposition on code via a blog post…the workaround is not ideal. It’s hard to tell at this point whether we’re misusing Unity or if Unity is limiting us. I’m going to say both…but what happens when we stop misusing the tool and are at that point restricted only by its limitations? Well, we’ll get there when we get there. We’re not there yet.
- Gathering requirements is still a problem, and it turns out business analysis skills are still valuable. The sky also remains blue.
- I’m not a fan of developing for the third-party grid we use, mostly because it reminds me of SharePoint, in how if you stretch the grid’s functionality in ways it was not designed to stretch, you end up in a world of hurt. And, it’s not a true WPF citizen, which affects a lot of things. Grids are the root of all evil. Strike that, the LOVE OF grids is the root of all evil.
- We desperately need end-to-end testing for WPF. And by we, I mean me. I’ve heard Project White works but is slow, but I haven’t heard any mention of anyone using it. Allegedly VS2010 also has UI automation facilities. Hopefully there’s a solution for this soon, and specifically, hopefully someone else invests their time, not mine, figuring all this out.
- I finally shelled out the money for R#. For code construction, you can probably do without R# and just use the built-in Visual Studio tooling (which I did for the longest time). But, on our medium-ish sized project, the navigation features alone are worth the price. I’ve also noticed that I seem to be the only person in my room that uses both a) the navigation menu (CTRL+SHIFT+G IntelliJ bindings) and b) the refactor menu (CTRL+SHIFT+R).
- I’m also frustrated by how R#’s intellisense gets in the way of typing more often that vanilla Visual Studio. When attempting to close R#’s intellisense, If in doubt, hit ESC five or seven times. Then wait a few seconds, then hit it another sixteen or seventeen times, to be sure.
- Third crucial R# keystroke: SHIFT+ALT+L – works almost like CTRL+ALT+L, but better. Having just typed these words, I know how dumb the last sentence reads, and I’m sorry, but there’s no improving it. Either you’re feeling the pain of CTRL+SHIFT+L, and discovering SHIFT+ALT+L fills you with great joy…or you have no idea what I’m talking about.
- R# 5.0 feature – update namespaces to match folders, or update folders to match namespaces – BOTH OPERATIONS WORK IN BULK! YESSSSSSSSSSSSSssssssssssssssssssss. Also, related, you can move entire folders at once. That scary namespace change is no longer scary.
I don’t know if any of you made it all the way through the long list, but even for those of you who got a flavor of what the updates are—for the most part these things that have held my attention for the last several months tend toward fundamental, classic issues.
This is my first time to blog directly about work, and I’m trying to toe the line—I don’t want to turn this into a “winning a work argument via my blog” blog entry. You know—when you argue about something dumb at work, summarily lose the argument, then later, still fuming, blog about how you would totally make Data human instead of give Geordi back his eyesight, totally, and how any dissenting opinions are wrong and weak. Then shift backwards in your beanbag, in a sort of smug, self-satisfied way. You’ve won! Sweet victory. Oh yes, sweet sweet internet victory.
Previously I’ve been the lone ranger, able to resolve arguments with myself peacably and without a public stir. But now I’m on a team of lone rangers…a loosely united federation of lone rangers. Or planets. The point is, there’s a bunch of us. And some of us speak fluent Klingon. I’ve got to watch myself a little more now, to make sure I’m not rehashing work arguments, or posting things that we need to “keep in the family.”
Hopefully the new content (content, not the jokes) is found useful by someone besides myself.