|
LATEST POSTS
Tuesday, April 28, 2009
Have been following Greg’s and Ayende’s online debate and one of Greg’s comments is an awesome tie-in to a half-written post that I can now complete. Its not just about YAGNI its about risk management. We make the decision early (Port/Adapter) that will allow us to delay other decisions. It also costs us next to nothing up front to allow for our change later. YAGNI should never be used without thought of risk management, we should always be able to quantify our initial cost, the probability of change, and the cost of the change in the future. Context in mind, let’s dance. My brother hates insurance. Despises the very concept of it. “You give all this money to ‘em and whaddaya get for it?” is his claim. He spends, say, $2000 each year for dental insurance for his family but his appointments cost only maybe $800. He’d rather put money away every month and use it for the various issues that are typically done through insurance. The problem with this philosophy is that he’s evaluating only the tangible benefits of insurance. From a total cash outlay perspective, he’s losing money. But, of course, insurance isn’t about making money. It’s about risk management. That is, there are risks involved with health and property and life. There is a possibility that something may happen to your health that requires you to pay a lot of money to fix it. And insurance is all about monetizing that risk. You pay someone else a certain amount of money so that they can assume the risk of paying a lot of money. So you can continue living your life as an extreme full-contact Cribbage player without worrying about having to cover the bills when someone slams down a head-rattling 24 hand when you’re about to peg out. For my own part, I love the idea. The implementation leaves much to be desired in most cases but I have insurance for pretty much anything that could go wrong: health, property, auto, life, distillery, heck, you can even find insurance against birth defects stemming from “open-minded” mating rituals if you look hard enough. And pay enough. In software development, risks are everywhere. External systems are a risk. Unmaintainable code is a risk. Having a high number of defects is a risk. Even the choice of technology is a risk. Where this becomes more touchy-feely comes in one’s aversion to risk. You can ignore risk in your project just like you can ignore it in life and not be insured. If the stars align, your project will succeed anyway. Your defects don’t get in the way of gaining market share, the external systems you have gel nicely with your project. But there is always the chance that risks become a reality. You may be tasked with developing a feature that will be nigh-impossible to wedge into your current architecture because you thought it would be easier to outsource to Drag ‘N Drop Data Access Inc. You may be facing a mob of angry customers because you’ve ignored your defect list too long. In order to protect ourselves, we need to constantly look for ways of managing our risks. I’ve mentioned unmaintainable code as one risk. How can we minimize it? Regular code reviews and pair programming are two options that immediately spring to mind. It’s a lot harder for two people to write bad code than one. Incorrect code is another big risk. I.e. code that doesn’t do what it’s supposed to. Mitigating that risk can be done with automated tests, regular communication with the client, basically doing anything in our power to recognize that code is wrong and ensure that, when fixed, it doesn’t become wrong again. External systems are another good example. Using someone else’s web service or library represents a risk to you. You don’t have control over how the code works. In the case of web services, you don’t even have control over when it could change. Adding an anti-corruption layer over it is one way you can ensure that your exposure to that risk is minimized. These are only examples. The underlying theme is to get you thinking about the risks on your project and how you can “buy insurance” to minimize it. Sometimes your insurance will be too “expensive”. That is, the cost to minimize the risk is too high based on your aversion to it. Maybe you trust the company providing the external service and you decide you want to take on the risk of binding directly to it throughout your application. Consider when people think: I’m not feeling any pain with that particular problem. There are undertones to that. “I haven’t experienced any losses from my actions” is one. Another: “I’ve evaluated the risks and I’m okay with it.” Another touchy subject: “Our developers aren’t capable of dealing with these ‘advanced’ topics.” What are the risks involved with that stance? That your code may not be as clean as it could be, maybe? That if you always code to the lowest common denominator, then that’s all you will attract on your team? Or the cost of insurance (i.e. cost of training, possible high turnover) is too high? It all depends on what your aversion to risk actually is as well as the cost of insurance against it. IoC containers are a relatively cheap insurance against the risk of highly-coupled code. They have a learning component but that’s typical in the industry. Choosing the “right” one also has inherent risks, of course, so many people avoid them on that basis alone. And here’s the thing with insurance: if all goes well, I hope my insurance company makes a pile of money from me. Because if they don’t, that means something has gone very wrong and they’ve had to cover some major catastrophe. If, <deity to be named on my deathbed> forbid, that happens, the last thing I want to worry about is whether or not I have the money to cover it. Back to software, we have the same concept. I could possibly write code that is loosely coupled and always correct without the aid of TDD or automated tests in general. That is, I could spend all this time testing and discover it’s wasted. This is what makes insurance such a porkypine to “love”. You buy it hoping you never have to use it. You actually *want* to never see any tangible benefit from it. But it’s sure nice when you need it. Kyle the Allegorical
Saturday, April 25, 2009
I’m over a month in with my new keyboard and, as promised, here is the follow-up. Typing speed has returned to more sporting level, as I had expected. The exercises included with the keyboard, while not Pulitzer Prize material, do help. I’d work on them on my host machine while waiting for my VM to boot up in the morning. Doing that, I was able to get through the ones I cared about in about a week. I’m still not *quite* at the same typing speed but I’m close enough. It’s the old 80/20 rule. I’ll get up to 80% of my old speed after 20% of effort. The last 20% will probably take orders of magnitude longer. That said, the keyboard does exactly what it advertises, which is reduce strain. All (keyboard-related) pain in my right arm has ceased. Whether it’s psychosomatic or the new keyboard layout or the fact that the keyboard releases a rush of endorphines every time I press Ctrl-Alt-E, I don’t much care. The fact is, the pain is gone. That alone makes the keyboard worth it’s weight in whatever metal is selling these days. As a bonus, I also discovered that Robin Williams used one in the blockbuster hit, Flubber. If that’s not endorsement enough, well, you can’t save everybody. To be fair, there have been a whack of other little adjustments I’ve made that have contributed to my new pain-free typing experience. I described a few in the original post: - Using Executor
- Remapping CapsLock and F1 to Esc (the former because it’s more convenient, the latter because the F1 key is the MOST ANNOYING KEY ON THE FACE OF THE PLANET!)
- Using AutoHotKey to remap Left-Control + Right-Control to Alt-Tab and Left-Control + Right-Win to Shift-Alt-Tab
In addition to this, I’ve also done the following: - Changed the default keystroke to Executor to Right-Control + Backspace
- Turn off the annoying double-click when you press CapsLock (aka Esc). This is a keyboard function and it was heavenly when I found out it could be disabled.
- Remapped the left backslash key on the keyboard to Insert.
- Mapped Win + F10, F11, F12 to Volume Mute, Volume Up and Volume Down respectively (with AutoHotKey)
- Made heavier use of ViEmu and Vimperator
With regard to the third point, for whatever reason, the keyboard comes with two backslash keys. This is strange given how sparse they are about duplicating other common keys (alt, win, etc.) and simply not including others (Insert, for example). Whatever the case, I’ve used the built-in keyboard remapping capability to remap the left-hand backslash to Insert which has helped immensely for logging into VMs. The last point is important. When I first tried both of these tools some months ago, I used them for a month and gave up, thinking I’d given them the good ol’ college try. Coming back to them, I was surprised how much I actually remembered. Which is good because it meant I could then learn some more keystrokes without having to also try to keep the original ones in my brain. The experiment was so successful that I added ViEmu for Word and ViEmu for SQL Server to my toolkit. All of them have helped me to avoid the arrow keys, PageUp, PageDown, Home and End, all of which are still not as intuitive as they ought to be. Oddly, I tried Vim itself for a few days and it was way too wacky for me. So I’m sticking with Notepad2 as my default text editor. I end up typing jjj and kkk a lot when I want to navigate but I can only take so much freakishly-obscure tools and hardware at once. Both ViEmu and Vimperator are as configurable as Vim, which may mean something to you if you know that Vim is very highly configurable. So I’ve added the following configurations to ViEmu for all versions: - noremap <Space> <C-d>
- noremap <BS> <C-u>
I’m not 100% sure what noremap does compared to map or nnoremap. Just know that adding the above two lines to _viemurc and _viemuwrc makes things happen. In this case, pressing Space will move text down half a page and pressing Backspace will move it back up again. This may seem odd to you but considering where these two keys are on a Kinesis, it’s very aesthetically-pleasing actually. For Vimperator, I essentially stole the configuration from someone else. The highlights of it are: - set complete=l
- au LocationChange .* js modes.passAllKeys = /(www\.google\.com\/reader)|(rememberthemilk\.com)/.test(buffer.URL)
- com gui :set guioptions+=mTb
- com nogui :set guioptions-=mTb
This is what these commands do: - Enable auto-completion when you open a url (either with :open or :tabopen)
- create a command called :gui which enables all the toolbars. The :nogui command hides them again.
- disable Vimperator for Google Reader and RememberTheMilk (i.e. automatically switch to pass-through mode for these sites)
For the last one, I had, at one point, also disabled Vimperator for GMail because it collided with many of the GMail shortcuts. The latest version of Vimperator is much saner with GMail so I’ve enabled it again. Still get an error when deleting mail with # and I can’t press Y to archive but it’s much better than before. There is still one major pain point: The location of some rather common characters in C#. Namely: []{}<>. These are all located in the same corner and I’m still tripping over myself as I type them. I’m working on a macro that will allow me to type out “left curly brace” and have it substitute { in its place. Kyle the Laconic
Monday, April 20, 2009
One of the more entertaining and satisfying sections Donald and I have written for Brownfield Application Development is on Development Project Archetypes. That is, the types of people you encounter on a development project. Donald’s been outlining them on his blog for the last couple of weeks and is about halfway through the list. To date, he’s covered: - The Ivory Tower Architect
- The Absentee Client
- The Disenfranchised Client
- The Process-Heavy PM
- The Front of the Magazine Architect
- The Ex-Tech Project Manager
Rest assured that developers themselves will not be spared before the list is through. Beware these people. And for the love of all that is hillbilly, don’t be any of them. Kyle the Cautionary
Sunday, April 19, 2009
The hillbilly is on a new project. Well actually, I’m on two new projects but I’m still working on how to Code Better on the one that involves stored procs in Oracle, a web site project (vs. web application project), a data access layer consisting entirely of static methods, and no unit tests except on the domain objects themselves. Suffice it to say that “maintainability” means very different things to different people. The other project has led me to investigate REST (or, more accurately, ReST but that’s the last time I’ll call it that because that looks too alt even for my tastes). The bulk of the work for the application is going to be done via JavaScript calls to services. So in my attempt to hammer that screw with ASP.NET MVC, my first reaction was: S#arp Architecture with judicious use of JsonResult. Luckily, my partner-in-crime is a little more rounded, and politely, but firmly, guided me away from MVC saying, “I ain’t building this app with that whore makin’ the rounds on every blog short of Wil Wheaton’s”, or something to that effect. Instead, he said a RESTful architecture may be more suitable for our goals. So I set about the task of investigating it. There is enough out there on REST that you can find on your own, starting with the Wikipedia page. But my English teacher always told me to understand something, you should put it in your own words. In keeping with that, REST is, to my thinking, a way of architecting your application based on resources and how they are accessed. Strictly speaking, it is implementation-agnostic but for my purpose, I find it useful to tie it to HTTP because that’s the canonical example and because, well, I’m building a web app. With respect to HTTP, REST de-emphasizes the URL (or, apparently more accurately, the URI) as the be-all and end-all of how to perform some action, like getting a list of possible moonshine bases or adding a new store to your designer clothing empire. Instead, the URL is a placeholder, basically a way of accessing the resource. What you want to do with it depends on other factors, like the HTTP verb used to get it and the data sent to the page in the HTTP header. For example, http://roadkilldiner.com/menuItem/3 could be a valid URL. But what it does depends on how you access it. If you use a GET verb, then you want to get the details of the menu item with ID 3. If you use a PUT (or POST, this is still kind of fuzzy to me), you would update it (or possibly add a new one with an ID 3, I think; hopefully some RESTful commenters will clarify that for me). In this case, you’d have to provide some more information to the URL in the header. Using a DELETE verb will automatically update it to the latest version of your application. I’m kidding, of course, you all know what DELETE will do. Incidentally, none of this says anything on how the menu item will be rendered when you do a GET. Maybe it will be XML, maybe JSON, maybe some proprietary format. When you make a request, part of the information you provide is how you want the item to be returned to you. If memory serves, I think the ACCEPT HTTP header determines this. Furthermore, HTTP defines a whole whack of return codes that we typically ignore. OK and PageNotFound are no strangers but there is also MethodNotAllowed, Created, and a bunch of others. Typically, I don’t pay any attention to them but in REST, this things have meaning and are part of the implementation. So to sum up, the URL is just the starting point, identifying the resource with which you want to work. What you do with it depends on a host of other data provided with the request and the status code that is returned. With that bit of understanding out of the way, my next step was to see how this could potentially be implemented in .NET. (Comment if you want on the futility of doing this in .NET, I’m already neck deep in new concepts on this project. I need C# as my safety blanket.) My first stop was still MVC and the SimplyRestful routing with MvcContrib. But that didn’t sit too well with me. It is, after all, a model-view-controller and we wouldn’t have a lot of need for the view part. In short, REST feels like an afterthought with respect to MVC. My cohort turned me on to WCF Rest Starter Kit and we were duly impressed at the veritable fountain of information available, particularly in the form of screencasts. After checking out a couple and playing with some demo services, this looked like a step in the right direction. It seems to gel with my understanding of REST, such as it is. HTTP verbs, different content types, a URL templating mechanism, all of this appears to be handled in some form or another. But in the back of my mind, a little voice kept saying “OpenRasta”, a framework I had followed to varying degrees over the last year or so. Based on the documentation, it seemed to be a different form of MVC implementation but with different syntax and better support for different content types. Let me say this up front, and I’ve told the project owner, Sebastien Lambla, the same thing, this documentation is to the detriment of the project itself because the demonstration he graciously gave (at my request, I should note) was impressive as hell. And it may be too soon to tell, but it looks much, much better than the WCF implementation. Admittedly, I had originally set up the demo primarily in order to answer some general REST questions because Sebastien always seemed to be talking about it and he’s a bright guy. I had a vague idea of what OpenRasta did but I was skeptical that it could replace the sheer magnitude of marketing force behind WCF REST Starter Kit. I’ll give you some samples from memory. Sebastien will likely chime in if they’re wrong. The following will return a Json representation of a MenuItem for a GET request: public class MenuItemHandler
{
public MenuItem Get( int id )
{
return new MenuItem { Id = id, OriginalSpecies = "Raccoon" };
}
}
That's it. Provided you do the proper configuration, of course, which is similar to setting up routes in MVC. But the highlights are:
- Class doesn’t need to inherit from a base class
- No need to manually serialize the object
- No need to manually specify the HTTP verb
- No need to specify the content type at all
Now, if you want to also return the object in XML format, here is what the code would then look:
// See above code
That is, your implementation code doesn't change. In the configuration, you tell it that you’d also like to be able to handle XML requests and that’s it. The framework does everything else for you. Provided you specify the content-type in the ACCEPT header, it will use the same method to return the object in JSON or XML format.
It gets better. If you want to return this in an HTML page that spits out all the properties, again, nothing changes. You change the configuration so that it accepts HTML requests, and you set up a view for it (similar to MVC), and that’s it.
By the way, this is only one alternative. If you want more control over your status code, you can do it in a slightly more MVC-ish way:
public class MenuItemHandler
{
public OperationResult Get( int id )
{
return new OperationResult.OK { ResponseResource = new MenuItem { Id = id, OriginalSpecies = "Raccoon" } };
}
}
I’m starting to get into areas where I may not be doing the syntax justice but the idea is the same. You can specify the exact HTTP status code you’d like returned with each method.
Handling the other HTTP verbs is a simple matter of adding the methods:
public class MenuItemHandler
{
public MenuItem Get( int id )
{
return new MenuItem { Id = id, OriginalSpecies = "Raccoon" };
}
public OperationResult Post( MenuItem menuItem )
{
// Update the menu item
return new OperationResult.Created { ResponseResource = menuItem };
}
}
All in all, colour us both very impressed. As I’ve mentioned, documentation is light and the beta and open-source nature of it may give one the willies. But given that we are both very new to REST, we got a nice warm fuzzy feeling that OpenRasta would lead us down the right path without: a) getting in our way, or b) hiding the details of REST that we need to understand to use it properly. Will report back after using it more but as it stands now, we’re basking in the afterglow of a demo gone right.
Kyle the Dazzled
Tuesday, April 07, 2009
I’m going to go out on a limb and posit that a few of you have attempted, and possibly succeeded, at integrating JsUnit into an automated build process. Assuming that is true, you people are off my Christmas card list for not blogging about it in such a way that it is discoverable by Google. (And that includes you, Miller). The sole exception to this is honorary hillbilly Toby Henderson who provided enough insight in the comments to Jeremy Miller’s post mentioned so disparagingly above. From that, I was able to come up with the following NAnt task (and Jayzus only knows how this is going to look in an RSS reader): <target name="jsunittests"> <property name="jsunit.port" value="9123" /> <property name="jsunit.authority" value="localhost" /> <property name="jsnuit.vdir" value="AdventuresInPlaid" /> <property name="jsunit.acceptor.partialurl" value="${jsunit.authority}:${jsunit.port}/jsunit/acceptor" /> <property name="jsunit.url" value=""http://${jsunit.authority}/${jsunit.vdir}jsunit/testrunner.html?testPage=${jsunit.authority}/${jsunit.vdir}JsUnitTests.aspx&autoRun=true&submitresults=${jsunit.acceptor.partialurl}"" /> <property name="jsunit.browserFileNames" value=""${programfiles.dir}\internet explorer\iexplore.exe,${programfiles.dir}\Mozilla Firefox\firefox.exe"" /> <property name="jsunit.log" value="logs" /> <property name="jsunit.resourceBase" value="" /> <property name="libs" value="" /> <foreach item="File" property="filename"> <in> <items> <include name="app\BookedIn.Web\JsUnit\java\lib\*.jar" /> </items> </in> <do> <property name="libs" value="${libs}.\lib\${path::get-file-name(filename)};" /> </do> </foreach> <property name="libs" value="${string::substring(libs, 0, string::get-length(libs) - 1)}" /> <exec program="java" workingdir="app\BookedIn.web\jsunit\java" commandline="-Dport=${jsunit.port} -DbrowserFileNames=${jsunit.browserFileNames} -Durl=${jsunit.url} -DlogsDirectory=${jsunit.log} -classpath ".\bin\jsunit.jar;.\config\;${libs}" junit.textui.TestRunner net.jsunit.StandaloneTest" /> </target> Assuming that’s copy-and-pastable into your own script, I’ll move on. The properties almost certainly should be moved outside of this target, of course. I’ve included them all here for convenience. Some of them are machine specific so putting them at the top means you can override them with a local properties file. The <foreach> loop in the middle was borne out of frustration. It will look through all the .jar files in the JsUnit lib folder and create a semi-colon-delimited list of them. This is then passed into the classpath for the <exec> task which launches the whole thing. My guess is that Toby used an older version of JsUnit because it appears there are a lot more libraries involved now. After about the third or fourth time running the task with a manually-entered list of libraries and having a ClassDefNotFound error come up, I sought out some help to just dump them all in with the <foreach>. Word of caution: the config folder included in the classpath contains xwork.xml. The part that caused us the greatest trouble was a message “Error loading configuration file xwork.xml”. This was because we were including the path to the xwork.xml file explicitly, rather than the path to just the config folder. It was the Ant file for JsUnit itself that eventually led to our salvation. So between this and the recent announcement that my wife is pregnant, all is well in Hillbilly House. Kyle the Expectant
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent
my employer's view in any way.
Copyright © 2010 Kyle Baley. All rights reserved.
|
|
|
CATEGORIES
|
|
LATEST POSTS
POPULAR POSTS
|
|
ARCHIVE
| March, 2010 (1) |
| February, 2010 (8) |
| January, 2010 (2) |
| December, 2009 (3) |
| November, 2009 (2) |
| September, 2009 (5) |
| August, 2009 (4) |
| July, 2009 (2) |
| June, 2009 (5) |
| May, 2009 (6) |
| April, 2009 (5) |
| March, 2009 (6) |
| February, 2009 (2) |
| January, 2009 (6) |
| December, 2008 (5) |
| November, 2008 (2) |
| October, 2008 (5) |
| September, 2008 (9) |
| August, 2008 (5) |
| July, 2008 (7) |
| June, 2008 (6) |
| May, 2008 (11) |
| April, 2008 (13) |
| March, 2008 (13) |
| February, 2008 (12) |
| January, 2008 (19) |
| December, 2007 (16) |
| November, 2007 (8) |
| October, 2007 (23) |
| September, 2007 (15) |
| August, 2007 (8) |
| July, 2007 (6) |
| June, 2007 (11) |
| May, 2007 (19) |
| April, 2007 (14) |
| March, 2007 (3) |
| February, 2007 (4) |
| January, 2007 (7) |
| December, 2006 (5) |
| November, 2006 (9) |
| October, 2006 (11) |
| September, 2006 (14) |
| August, 2006 (11) |
| July, 2006 (15) |
| June, 2006 (8) |
| May, 2006 (10) |
| April, 2006 (12) |
| March, 2006 (3) |
| February, 2006 (7) |
|
|
|