That’s the last time I ever ask for a Doggy Bag!
And that’s not food the Dog is looking at.
If you're interested in Domain Driven Design, make sure you follow Casey's series on the subject. He does a very good job of explaining things clearly and answers many obvious questions that one initially asks when starting with DDD. Make sure you check out the comments also.
According to you Jeff, 80% of developers are people that don't care much about improving the quality of their craft. In other words, it's mostly those who just care about the paycheck…programming is a job that pays the bills.
The remaining 20% fall in the category of those that read your blog (note the part in Italics):
But here's the paradox: the types of programmers who would most benefit from these guidelines, rules, principles, and checklists are the least likely to read and follow them. Throwing a book of rules at a terrible programmer just creates a terrible programmer with a bruise on their head where the book bounced off. This is something I discussed previously in Mort, Elvis, Einstein, and You:
Thus, if you read the article, you are most assuredly in the twenty percent category. The other eighty percent are not actively thinking about the craft of software development. They would never find that piece, much less read it. They simply don't read programming blogs– other than as the result of web searches to find quick-fix answers to a specific problem they're having. Nor have they read any of the books in my recommended reading list. The defining characteristic of the vast majority of these so-called "vocational" programmers is that they are unreachable. It doesn't matter what you, I or anyone else writes here — they'll never see it.
In the absence of mentoring and apprenticeship, the dissemination of better programming practices is often conveniently packaged into processes and methodologies. How many of these do you know? How many have you practiced?
Yet at the same time, as author of this blog and thus falling in the 20%, you state:
All those incredibly detailed rules, guidelines, methodologies, and principles? YAGNI. If it can't be explained on a single double-spaced sheet of paper, it's a waste of your time. Go read and write some code!
So which is it Jeff? Do we or don't we try and improve ourselves?
I don't fall into either of the groups, I'm not a Coding Horror. I'm one of those guys that tries to improve my knowledge, I try and learn continuously, either by myself or with the help of those that surround me. I don't just throw it all out of the window and claim that if there isn't a mentor around to help me, screw it. I don't give up if I can't understand it in a few hours. If others do differently, I try and understand why they do it differently.
To claim that I'm not going to need to, or not change my ways is very arrogant on my behalf. And the best thing is that I'm not alone. There are thousands of others like me.
So please Jeff, don't corrupt the profession just to justify your own ways.
[And to my reader (Hi Mom!), I will do my utmost best to refrain from writing any more posts about Coding Horror]
Given the following action:
1: public ActionResult About()
2: {
3: return View();
4: }
5:
and the following test:
1: public void About()
2: {
3:
4: // Arrange
5: HomeController controller = new HomeController();
6:
7: // Act
8: ViewResult result = controller.About() as ViewResult;
9:
10: // Assert
11: Assert.IsNotNull(result);
12: }
Come up with as many way as you can to break the test.
(This is the default code generated with a new ASP.NET MVC application)
My mother wants to become a computer programmer (not to be taken literally). And guess what, she can. With all the RAD environments nowadays you really don't need to know much about the basics of programming to make applications. You can use anything you want. First step, pick an environment. You have lots to choose from (Visual Studio, Delphi, Ruby on Rails). In under 1 hour you'll have your first application working. Next step, sell it.
Now do this for about 10 years, making a profit and you can claim that you're successful in software development. You can claim you've worked for 10 years and have never had to worry about things such as polymorphism, delegation, etc.
So when someone comes along with a post talking about weird things such as SOLID or how rules are meant to be broken, you reaffirm your position as a successful developer that has never needed or understood these concepts. And since the person writing this has 1.5M visitors a month and 125K subscribers, it's OK!
(You think I'm crazy. Read some of the comments on this post).
But It's NOT OK
I don't lose sleep over what I term demoware cowboys. Everyone has a right to make a living, however way they want. I'm the first person in the room that stands up to defend not needing to graduate in CS to have a successful career in software development. However, I also defend studying, understanding and practicing software engineering, and to continuously improve yourself. Just because you sell software and put food on the table doesn't mean you've accomplished all there is to in your field.
What does bother me however is people talking about things without truly understanding them. It's important to act with responsibility, specially when having so many followers.
Some of us write software for a living, as opposed to just writing about it, and it's not only about getting the job done.
Take a look at this code:
1: public class ClassToTest {
2:
3: public void MethodToTest()
4: {
5:
6: IDAL dal = new DAL();
7:
8: int discount = dal.GetDiscount();
9:
10: if (discount > 10)
11: {
12: // Do something
13: }
14:
15: }
16: }
The tight coupling to DAL just stands out like a sore thumb. One consequence of this tight coupling is that it's hard to test if we don't have an underlying database setup with correct values. Forget about testing this while taking a shower, unless you have a habit of taking your SQL Server box to the bath tub with you.
Take a look at the following approach to making this code testable without having a database:
1: public class ClassToTest {
2:
3: public void MethodToTest()
4: {
5:
6: DAL dal = new DAL();
7:
8: #if testing_in_shower
9: int discount = 3;
10: #else
11: int discount = dal.GetDiscount();
12: #endif
13: if (discount > 10)
14: {
15: // Do something
16: }
17:
18: }
19: }
Are you still here? Didn't you just fall off of your chair, not knowing whether to laugh or cry in anguish? It's just plain wrong isn't it? Code Smell just takes on a whole new dimension (and consistency?). Something like this shouldn't be done for many reasons. It makes our code testable but it's wrong.
Introducing code for testing purposes
The reason I bring this up now is because in the past 2 weeks I've seen a few references and examples of introducing code just for the sake of testability. Two weeks ago I was skimming over an article that was explaining unit tests. The class the author was trying to test had a dependency that was causing issues during his tests. The solution offered was to introduce a new constructor and inject the dependency in. In our case, the ClassToTest would like:
1: public class ClassToTest {
2:
3: public ClassToTest()
4: {
5:
6: // Initialize some stuff
7:
8: }
9:
10: public ClassToTest(IDAL dal)
11: {
12: // Initialize some stuff
13: _dal = dal;
14: }
15:
16: ....
Now that's great. The problem is that the author left both constructors in there, emphasizing that one is for testing purposes and the other for production code. Why that's wrong I'll get to in a moment.
The other day, Scott Hansleman made a blog post on testing some code that had a dependency on the current principal. His solution was to inject IPrincipal into various methods of the Controller, where Controller is in the context of an ASP.NET MVC Controller. Personally I don't agree with the solution but that's another subject (and another post on a different approach I have in the backlog for the same scenario). However, injecting the dependency seemed valid enough. Later on he updated the post with the following:
UPDATE: Phil had an interesting idea. He said, why not make method overloads, one for testing and one for without. I can see how this might be controversial, but it's very pragmatic.
- [Authorize]
- public ActionResult Edit(int id)
- {
- return Edit(id, User); //This one uses HttpContext
- }
[Authorize] public ActionResult Edit(int id) { return Edit(id, User); //This one uses HttpContext }You'd use this one as before at runtime, and call the overload that takes the IPrincipal explicitly for testing.
The same thing has happened as in the case of an overloaded constructor. Code has been introduced into the base just for the sake of testability. In the previous case it was a new constructor, and in this case, a new method.
Why is this wrong?
Introducing code just so that you can test it is wrong for several reasons, including an increase in noise, decrease in readability and more importantly, permitting the possibility of production code that will not be tested. It might seem improbable at first, seeing that the overloaded versions always call the base ones, but as your code base grows, by allowing this habit, you can promote it to other structures such as conditionals, switch statements, etc, and not limit it only to methods or constructors. Then you'll start initializing values that only make sense in tests and gradually your code starts to smell more and more. To top it off, you can throw in some compiler conditional that rips those parts of the code out from the production version.
Code should also serve as documentation. The cleaner you make your code, the less noise and redundancy you add, the easier it is for others to understand and maintain.
Conclusion
Being pragmatic is good, but don't do it at any cost. Try and not introduce code into your code base that is there exclusively for the purpose of testability (and no, dependency injection is not only for testability). Anything that has to do with testing, keep it where it should be, in the test assemblies. Having overloaded methods or constructors, mocks or stubs in your code base is just as bad as having compiler conditionals in your code for testability. If you run into issue where your code is hard to test, step back and re-think your design. Maybe the problem you're facing now that's impeding your tests is actually a can of worms waiting to be opened. And the sooner you open it, the better. That's one of the great advantages of Test Driven Development.
Just reading a comment on Uncle Bob’s blog by a guy called Ted.
What’s with this whole TDD/SOLID and Podcast stuff?
Just because you practiced TDD does not make your code clean nor high-quality.
Let’s face it, most TDD practitioners are “DEVELOPERS”. You are not “QA”, “TESTER”, “SDET”. What do you know about various testing techniques, testing principles, testing metrics, how to test, etc?
Do our field a favor TDD-er, do the following:
- How We Test Software at Microsoft
- Go to MS and apply for SDET position (or Google)
- Read more books about Software Testing
- Ask yourself if you wrote great TDD code or not
Now for the last question, if the answer is “Yes”, then you’re a Tester. If the answer is “No”, then you’re a developer. And obviously, if you are a developer, you suck at TDD.
It’s just how the brain is wired or perhaps it’s in your training. Developers are almost always bad testers, vice versa.
Maybe TDD should be renamed "Coming up with a good design by first trying to use my code Driven Development". There is an overwhelming amount of information regarding Test Driven Development and yet, still, STILL, people think it’s about testing.
I’ll be doing an Introduction to jQuery tomorrow at our local user group. It will cover a bunch of goodies including the basics, Ajax and extending jQuery. The talk will be pretty much the same in contents as the one I’ll be giving at BASTA in about 2 weeks. Obviously tomorrow’s is in Spanish
. There’s already 25 people signed up and although there’s limited space, feel free to come by even if you haven’t signed up. We’ll finish off the evening with a round table discussion.
So I decided to top-up my Skype credit tonight. The red 0,66 € was just making my eyes sore. Since I had some credit in PayPal, I thought I’d use that. Going through the payment process I was presented with a screen asking if I’d automatically like to have Skype charge PayPal every time my balance falls below 2 €.
Obviously I unchecked that option and proceed to "Buy Now". I then got this next screen:
See the Always Pay with PayPal? Where did my options go? Just because I want to pay with PayPal this time I’m agreeing to always pay with PayPal? But what’s even worse is the description "I authorize Skype to charge my PayPal account for recurring payments". No I don’t. But where’s my option? Where did you ask me this? It wasn’t the 2 € option was it? Even if it was I ticked no.
And look at the next step. I can’t go back. I have to click the X icon and hope nothing happens.
I started using Skype back when there were somewhere around 50.000 users. There’s currently 16M users online right now. Back then, you couldn’t even purchase credit from Spain; they thought we all had stolen credit cards. We’ll get there eventually I guess…
I was just reading the transcript from the StackOverflow podcast nº 38. I came across it via a post from Jeremy Miller’s blog, since I normally don’t listen (actually I’ve never listened) to the StackOverlow podcast. Well it seems that there’s been some comments regarding this particular podcast, since Jeff Attwood, of Coding Horror fame made some comments about not caring about quality. No doubt I disagree, but this particular post is my beef with some of the other things mentioned in this podcast.
I don’t know how long Jeff or Joel have been programming, and to be frank I don’t care. I do know how long I’ve been at it. I’m not going to bore you with the details, but suffice to say that it’s been long enough and I’ve made some terrible mistakes and suffered the consequences while writing code and managing teams. We all live and learn, and one of the best ways to learn is from making mistakes. What I do care about however, (care maybe too strong of word, maybe "bothers me" is better) is people talking about things without proper knowledge.
Joel starts talking about Test Driven Development and 100% test coverage, which is not correct, and says:
…breaks 10% of your unit tests. Intentionally. Because you’ve changed the design of something… you’ve moved a menu, and now everything that relied on that menu being there… the menu is now elsewhere. And so all those tests now break.
Now I’m not even going to question what a menu position is doing in a unit test, but normally if you design your tests correctly, if something breaks it means it’s broken. It means the change has caused a test to break, and that is a GOOD thing. If your tests are breaking when they shouldn’t then your tests are maybe wrong. If you have to update the tests so they pass, then you’ve most likely changed the design, but you’re explicitly acknowledging this.
He then goes on to talk more about unit tests:
make in maintaining those unit tests, keeping them up-to-date and keeping them passing, starts to become disproportional to the amount of benefit that you get out of them.
I’m curious how benefit is actually being measured here, not to say that the statement is an oxymoron if your tests serve their purpose.
The next part I’m perplexed with:
Last week I was listening to a podcast on Hanselminutes, with Robert Martin talking about the SOLID principles. (That’s a real easy-to-Google term!) It’s object-oriented design, and they’re calling it agile design, which it really, really isn’t. It’s principles for how to design your classes, and how they should work. And, when I was listening to them, they all sounded to me like extremely bureaucratic programming that came from the mind of somebody that has not written a lot of code, frankly.
I’m all against acronyms, but please understand things before making statements about it. Nothing in SOLID is bureaucratic. And to say that people that apply SOLID have not written a lot of code, frankly, is just plain bullsh*t. I would say quite the contrary. I would say that people that have written a lot of code, know the side-effects of introducing changes, and how things can blow up in a million places, understand how code without tests can make your life miserable, how you worry about every other deployment you make because you don’t know if the changes you made have broken the estimate calculations, or whether negative values can still be invoiced correctly, these are all things that make you appreciate more principles such as Single Responsibility or Open-Closed Principle.
Joel then goes on to talk about interfaces:
So, you’ve got some class, with 40 different little methods on it, and I’m only going to use six of them, so I should make an interface with those six things that I can use, and the class will implement that interface, and that’s my contract with the class, that those are the only six things I’m going to use.
Is it only me that thinks this whole paragraph is nonsense? Have you completely missed the point of what an interface is Joel?
And then we come across the fileophobia:
Because what they’re doing is spending an enormous amount of time writing a lot of extra code, a lot of verbiage, a lot of files, and a million little classes that don’t do anything and thousands of little
I’ve said it a million teams: you’ll have other sh*t to worry if you ever hit the NTFS file limit per directory.
Continuing:
This seems to be where a lot of the Object Oriented Design community went, and if anybody has any strong feelings about this, call in and tell me what you think–tell me if I’m totally off track here–but it seems to me like a lot of the Object Oriented Design principles you’re hearing lately from people like Robert Martin and Kent Beck and so forth have gone off the deep end into architecture for architecture’s sake.
Joel, I’d love to come on your show and tell you you’re completely off track but I’m sure there’s tons of other people more qualified than me that can do the same. This is not about architecture for architecture sakes. This is about not developing DemoWare applications that blow up every time you make a change and end up costing you more time in debugging and saving face with your customer than it would have if you had done things correctly from the start.
Jeff goes on to talk about his quality views, which sparked many of the posts:
… There was this quote from Frank Zappa: "Nobody gives a crap if we’re great musicians." And it really is true. The people that appreciate Frank Zappa’s
See I think that’s where you’re wrong Jeff. I do care if I’m a good coder and I care if those on my team are good coders. Not because I can walk into a room and say I’m a great coder, but because I know it pays off in the long run. And Joel/Jeff, you can only appreciate what you’re talking about in your podcast if you’ve truly been coding for years.
[delphi]