tag:blogger.com,1999:blog-253408772024-03-13T10:07:39.664-07:00the ramblings of a .net dudemy thoughts on the art of writing software.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.comBlogger66125tag:blogger.com,1999:blog-25340877.post-53168246018510477372012-07-11T20:16:00.001-07:002012-07-11T20:16:45.465-07:00movedi've decided to move my blog. the new address is <a href="http://blog.earaya.com">blog.earaya.com</a>.
if you care to know why i decided to move, take a look at <a href="http://blog.earaya.com/blog/2012/07/11/hello-world/">this post</a>.
other than that, i hope to see you at the new url.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0tag:blogger.com,1999:blog-25340877.post-7234698214521913552012-03-11T20:51:00.001-07:002012-03-11T20:51:16.805-07:00utah code camp - spring 2012i went to code camp yesterday. unfortunately, most of the talks i attended weren't very good. on one of them, the speaker had trouble with his demo, and on the other, the speaker was hardly prepared at all.<br />
<br />
merrick christensen, however did a great job on his presentation "the browser as the platform". also, on the "test driving javascript" i learned i never want to use knockout.js in my life. why you'd want to litter your markup with their bindings is really beyond me... but whatever, to each their own.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com1tag:blogger.com,1999:blog-25340877.post-76231768471215488972011-08-10T07:26:00.004-07:002011-08-17T07:42:59.152-07:00Exception Usage ConsiderationsIt seems that I always have the following conversation with different developers.
<br />
<br />Them: This method shouldn't throw an exception, it should return an error code.
<br />Me: OK. Why?
<br />Them: Because... umm... exceptions are a terrible means to communicate errors. I want to see a status flag and an error message.
<br />
<br />I kinda get the point, but in frameworks such as .NET and Java, it really doesn't make sense to use anything but exceptions.
<br />
<br />First, if you use error codes or anything of the sort, you now have the <span style="font-weight:bold;">worst</span> of both worlds: the runtime and class library code will throw exceptions and your code will return error codes. Now you have to deal with both.
<br />
<br />Second, when returning error codes and messages you have to make assumptions about how application developers will use your code. It's impossible for you to determine under what conditions your code will be used and what assumption the application developer will make about it. It's best to just be consistent and throw an exception when you're not able to complete the work you "contracted" to do through your method signature.
<br />
<br />In the interest of completeness: there's perhaps one case in which you should return a flag instead of throwing an exception. When you have a method that gets called frequently and it also has a high failure rate, you'll likely experience a performance hit (from throwing/handling so many exceptions) that won't be tolerable.
<br />
<br />Microsoft, for example, had the above problem with the <span style="font-weight:bold;">Int32.Parse</span> method. To address the issue MS introduced <span style="font-weight:bold;">TryParse</span>. This new method returns a flag telling you whether worked and returns the value of the parse in and output parameter called <span style="font-weight:bold;">result</span>.
<br />
<br />It's important to note, however, that the boolean flag returned only indicates one type of failure: the method's inability to parse the string into an integer. The method still throws an <span style="font-weight:bold;">ArgumentException</span> if the argument is not valid.
<br />
<br />So there you have it: always use exceptions. And if you're not going to listen to me, use error flags to indicate just one type of error.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com1tag:blogger.com,1999:blog-25340877.post-54622013332940997312011-05-03T20:24:00.007-07:002011-05-16T15:31:42.273-07:00Injection with Unity: Mind Your Lifetime DependencyFor the past few months we've had this bug (PROD only, and unreproducible in any of our other environments) where every now and then we could not get data from our DB. The DB was up and running just fine, but the SqlClient on the web server just could not read the data (we'd get 2 errors: one about trying to read data where a reader was already open, and another about not being able to cast the data from the reader to a certain type). In case you're interested, the exact errors were:<br /><ol><li>System.InvalidCasException: Specified cast is no valid. At System.Data.SqlClient.SqlBuffer.get_Int32()</li><li>Invalid attempt to call Read when reader is closed. Somewhere in System.Data.SqlClient as well.<br /></li></ol>For a while we just lived with the error; it didn't happen very often and it only affected a few customers. Then the problem got worse and so we immediately blamed it on some environment change... we recycled the app pool on a consistent basis while trying to figure out what the problem was.<br /><br />Finally, when the problem got bad enough, I did a little bit of research and concluded that we were seeing the problem because we were not disposing our LINQ contexts correctly. After trying to prove that the problem was in someone else's code (and failing), I quickly concluded that it must be Unity that was not disposing the contexts.<br /><br />You see, I had assumed that Unity would new up an instance of our db context on every call to resolve, but it turns out that by default the lifetime of the dependencies Unity resolves is the same as the lifetime of the IoC container. In our case, the IoC container stayed alive throughout the entire app (because we needed to resolve stuff in our MVC controllers) and so the longer the app went without a restart, and the more requests it handled, the more we saw the error.<br /><br />Fortunately, because we were using Unity to resolve all of our dependencies, and because the Unity code was all in one place and well isolated from the rest of the app, it was really easy to fix. All I had to do was write a per HTTP request lifetime manager and plug it into our container. I'll be posting the code for that container soon... but now I gotta go to bed. Looks like we'll have quite a few bugs to fight tomorrow. :)<br /><br />Edit:<br /><br />As promised, here's teh code for the "per HTTP request" Unity lifetime manager:<br /><br /><pre name="code" class="brush: csharp">public class HttpRequestLifetimeManager : LifetimeManager<br />{<br /> private string _key = Guid.NewGuid().ToString();<br /><br /> public override object GetValue()<br /> {<br /> if (HttpContext.Current != null && HttpContext.Current.Items.Contains(_key))<br /> return HttpContext.Current.Items[_key];<br /> else<br /> return null;<br /> }<br /><br /> public override void RemoveValue()<br /> {<br /> if (HttpContext.Current != null)<br /> HttpContext.Current.Items.Remove(_key);<br /> }<br /><br /> public override void SetValue(object newValue)<br /> {<br /> if (HttpContext.Current != null)<br /> HttpContext.Current.Items[_key] = newValue;<br /> }<br />}<br /></pre>Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0tag:blogger.com,1999:blog-25340877.post-48708745935060314782011-01-20T22:12:00.005-07:002011-01-21T15:42:23.090-07:00write lesshonoring the title and idea of this post i'll just say this to get the point across:<br /><blockquote>the quality of your solution is inversely proportional to the amount of code you write to solve the problem.<br /></blockquote><br />unfortunately, i have to say a bit more to justify my thoughts.<br /><br />i've always wondered about how to write good code; and i'm not the only one apparently:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://imgs.xkcd.com/comics/good_code.png"><img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 455px; height: 695px;" src="http://imgs.xkcd.com/comics/good_code.png" alt="" border="0" /></a><br />well, i've finally figured it out: good code is written by writing as little code as possible. this is true because the when you write the bare minimum you will almost naturally end up with code that is easy to read, easy to test, easy to extend, and therefore, easy to maintain (to see more about the attributes of good code, take a look at <a href="http://www.makinggoodsoftware.com/2009/05/07/the-pyramid-of-code-quality-the-5-characteristics-of-good-code/">the pyramid of code quality</a>).<br /><br />i understand that there are guidelines and principles that you must still follow when writing "just enough" code, but things really deteriorate fast when you don't KISS.<br /><br />so next time you're inclined to do solve a problem with code, first think about if there's a way to solve it without <span style="font-style: italic;">any </span>code. then, and only if you absolutely must, write as little code as possible.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0tag:blogger.com,1999:blog-25340877.post-20562630791199063612010-10-26T19:14:00.002-07:002010-10-26T19:35:24.232-07:00SimplicityA couple of days ago while on my way to work, I was listening to Erno Rubik on an interview on NPR (yeah, I know, leftist media). <br /><br />At one point the host (Doug Fabrizio, I believe) asked: "Why did you choose a cube? Why 9 squares on each side of the cube?" To which Mr. Rubik answered something to the effect of: <br /><br /><blockquote>Well, I was trying to come up with the simplest solution possible. And that actually turned out to be very hard; it's always very hard to define something in it's simplest terms... (and a few more minutes of explanation about why reaching simplicity is so hard) Anyhow, I wanted to find the simple form to teach my students how to describe movement in mathematical terms; a cube with nine squares was the simplest way I could do that.</blockquote><br /><br />I just loved that answer. I've long had a feeling that when writing software the simplest solution will always be the most maintainable solution. Simplicity is the core principle on which YAGNI, DRY, and so many other software engineering ideas are built. As DaVinci said:<br /><br /><blockquote>Simplicity is the ultimate sophistication.</blockquote><br /><br />So here's this post in honor of writing <span style="font-style:italic;">simple</span>, sophisticated code. Long live simplicity!Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0tag:blogger.com,1999:blog-25340877.post-67836283441209183982010-05-11T08:37:00.005-07:002010-05-11T09:10:12.418-07:00Visual Studio 2010 Debugger Not Attaching ProblemSince we moved to Visual Studio 2010, I've had 3 people ask me: "Is there some sort of magic you have to do to get VS2010 to attach to the IIS worker process (w3wp)"?<div><br /></div><div>So, in the interest of (hopefully) saving you some time, I figure I'd write a little bit about what the problem with the VS2010 debugger is. Actually, the debugger is fine, it doesn't have any problems attaching; it's actually VS2010 itself that has a minor bug(?) while attaching.</div><div><br /></div><div>As you can see in the image below, under normal circumstances Visual Studio automatically detects what type of code the process is running and automatically chooses the correct debugger:</div><br /><div><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_U0AuZcqOces/S-l8Mxj22BI/AAAAAAAAAHs/Z33S0t13fa0/s1600/vs2010debugger.JPG"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 268px;" src="http://1.bp.blogspot.com/_U0AuZcqOces/S-l8Mxj22BI/AAAAAAAAAHs/Z33S0t13fa0/s400/vs2010debugger.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5470039781322184722" /></a><br /></div><div><br />Unfortunately, however, I've found that sometimes VS2010 cannot detect the correct code type in the worker process and attaches to the process using the .NET 4.0 debugger (I don't know why this happens nor do I know if this happens when attaching to other processes).<br /><br />If you attach using the wrong debugger, you'll attach, but you'll notice that none of your symbols ever load and therefore none of your breakpoints ever hit. It's actually somewhat frustrating because everything looks like it should be working but doesn't.<br /></div><div><br /></div><div>But enough talk about the problem; here's all you need to do to solve the problem if you notice you're not using the right debugger:</div><div><ol><li>Hit the "Select" button the in "Attach to Process" window.</li><li>Select the "Debug these code types:" radio button</li><li>Check all the code types you want to debug.</li></ol><div>You're shooting for something like this:</div><div><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_U0AuZcqOces/S-mAyIVo9GI/AAAAAAAAAH0/_MeORGoNavI/s1600/vs2010debugger2.JPG"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 209px;" src="http://4.bp.blogspot.com/_U0AuZcqOces/S-mAyIVo9GI/AAAAAAAAAH0/_MeORGoNavI/s400/vs2010debugger2.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5470044821138240610" /></a><br /><br />I've found that after you choose the code types you want to debug, VS2010 remembers your selection, so you should never have problems attaching in the future.<br /><br />Now, if I could just get rid of that stupid dialog asking me to confirm if I really want to attach to the "potentially dangerous" w3wp process, I'd be set. :)<br /></div></div>Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com5tag:blogger.com,1999:blog-25340877.post-45444763312701822512010-01-13T17:28:00.004-07:002010-10-26T19:36:49.506-07:003 Simple Rules To Good Object Oriented CodeMike and I had a long discussion about <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">BDD</a> last night. After he complained about how BDD didn't lead him to the solution he <span style="font-style:italic;">wanted</span>, I said something to the effect of "You know, the only reason we have all these design methodologies is because we don't really know how to think OOP and write OOP".<br /><br />At this point, before I continue, I need make something clear: I don't know what I'm talking about; all I know about BDD is what Wikipedia says about it. But I do know that writing good OO code doesn't require 3 different methodologies. All it requires if for programmers to think like objects.<br /><br />I like to think that good OO comes down to 3 simple rules:<div><ol><li>Objects are all about behavior; not attributes. If attributes defined objects, a cat and a dog would pretty much be the same thing since they both have eyes, noses, legs, etc.</li><li>Objects are discrete things from which you can build other things. They're a lot like <a href="http://adotnetdude.blogspot.com/2009/06/how-to-write-reusable-software-lesson.html">LEGO blocks</a>. Incidentally, code reuse is a byproduct of good OO code, not the purpose of it.</li><li>Objects like to be autonomous self directed entities. Objects don't like "managers"; if your code has lots of managers, you're probably doing something wrong. Objects like to coordinate their work through events; they don't like managers telling them exactly what to do at every point.</li></ol><div>A bonus rule: Composition is usually better than inheritance; it gives you a lot more flexibility when having to change behavior.</div><div><br /></div><div>To be honest: I'm mostly writing this because I'd like to hear from others what guiding principles you should have in your head when coding. Do we really need a lot of process if we just in our guts <i>know </i>how to write OO code?</div><br /></div>Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0tag:blogger.com,1999:blog-25340877.post-38500978215304213832009-10-28T19:49:00.003-07:002009-10-28T19:58:46.228-07:00The hardest thing about programming.When asked what the hardest thing about programming is, Bill Gates answered:<br /><blockquote>The hardest part is deciding what the algorithms are, and then simplifying them as much as you can. It’s difficult to get things down to their simplest forms. You have to simulate in your mind how the program’s going to work, and you have to have a complete grasp of how the various pieces of the program work together. The finest pieces of software are those where one individual has a complete sense of exactly how the program works. To have that, you have to really love the program and concentrate on keeping it simple, to an incredible degree.</blockquote>What's interesting, however, is that the hardest thing about programming is also the best thing about programming.<br /><br />I love programming because learning it is relatively easy, but mastering the art is extremely difficult. Like Gates says, reducing things to their simplest form is difficult - but fortunately, it's also beautiful. It's also true that the finest software is written by those who love the program and make a deliberate effort to keep it simple - and again, although difficult, being able to model an entire system in your head is pretty awesome!Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0tag:blogger.com,1999:blog-25340877.post-53918424448025921702009-10-06T10:54:00.003-07:002009-10-06T16:33:23.393-07:00Simple Events In ASP.NET MVCWe've been busy improving our customer facing applications. Our new marketing VP noticed some significant improvements that could be made in the workflow of our customer acquisition funnel.<br /><br />Making the changes that our marketing VP recommended required some major code changes so we took the opportunity to move our web apps into ASP.NET MVC.<br /><br />One of the early decisions we made was to put as little business and application logic on our controllers as possible. Finding a place for business logic is straightforward most of the time; it usually belongs in your (domain) Models.<br /><br />Placing application logic in the right place gets a little more complicated. We don't really have services for stuff like sending out emails, etc. so we have to write classes to do all that work. <br /><br />Invoking email code, authentication code, etc. right in the controller is an ugly solution. To solve our problem, I came up with a simple eventing mechanism that allows us to move all application code out of our controllers.<br /><br />Let's first start with what the code in one of the controllers would look like:<br /><pre name="code" class="csharp"><br />[AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken]<br />public ActionResult Index(IndexModel model)<br />{<br /> //code to interact with your model goes here.<br /> <br /> //And now the event code:<br /> AcmeEvents.Raise(new IndexRanEvent { IndexModel = model });<br /><br />}<br /></pre><br />The great thing about the code above is that all sort of things could now happen once your index runs; there may be 1 or N subscribers to the event above. Furthermore, you could (at run time) change the code that runs when the event triggers... but I'm getting ahead of my self; we'll look at how that could happen in just a second.<br /><br />Let's now look at the "raise event code". To do this, I decided to just use Unity's IoC container to resolve the code should trigger when the event get's raised:<br /><br /><pre name="code" class="csharp"><br />public static void Raise<T>(T args) where T : IAcmeEvent<br />{<br /> foreach(var handler in unityContainer.ResolveAll<Handles<T>>())<br /> {<br /> handler.Handle(args);<br /> }<br />}<br /></pre><br />Some assumptions the code above makes: (1) IAcmeEvent has a Hanlde method; (2) by the time the Raise method runs, the IoC container must have been initialized to map the different "event types" to the specific implementations that will execute.<br /><br />How you initialize the container is really not that important: you could do it in code, through a config, or any other method of your choice. What is important, however, is that when you initialize your container, you do it in such a way that code from other assemblies can execute. If you do this, you could literally just drop assemblies in your application and add to or change the behavior of your app.<br /><br />So there you have it; a simple eventing mechanism to keep your MVC controllers unpolluted from application logic. I'm really happy about coming up with this solution; I hope you find it useful too.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com1tag:blogger.com,1999:blog-25340877.post-53331338335303728432009-08-05T13:37:00.010-07:002009-08-05T14:37:06.991-07:00Barricading Your CodeYou've heard it a million times: "Never trust your inputs". Or maybe you've heard its corollary: "Always sanitize your inputs". Easier said then done, right?<br /><br />I'd like to show you a way to <span style="font-style: italic;">barricade</span> your code so that you can always sanitize your inputs without littering all of your code with sanitation code.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/en/2/24/Nassauwall.JPG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 303px; height: 224px;" src="http://upload.wikimedia.org/wikipedia/en/2/24/Nassauwall.JPG" alt="Wall Street Barricade" border="0" /></a><br />The key to writing good sanitation code is controlling <span style="font-style: italic;">where and how</span>you accept external input. Just like the barricade in the image above, traffic can <span style="font-style: italic;">only</span> flow on the sidewalks and not on the street.<br /><br />Here's how to accomplish the same with code:<br /><pre name="code" class="csharp"><br />public class ClassThatUsesBarricade<br />{<br /> public void DoWork(string inputOne, int inputTwo, ...)<br /> {<br /> //sanitize inputs<br /> RealDoWork(inputOne, inputTwo, ...);<br /> }<br /><br /> private void RealDoWork(string inputOne, int inputTwo, ...)<br /> {<br /> //don't worry about inputs because no external class could have called this.<br /> //do work<br /> }<br />}<br /></pre><br />By writing code like the code above, you've barricaded your class: data can only flow into your class through the public method. The private method can absolutely, 100% or your money back, trust its inputs without having to worry about sanitizing them. This way, your real work method can be short, and concise - after all, a method should only do one thing, and do it well.<br /><br />If your class has a lot of methods with very similar signatures that do similar things, you might want to reverse the code I showed: you could have a private sanitation code that all public methods that actually do work call. However, that's not really barricading your important methods... at some point you could forget to call the private sanitation method (ie. set up your barricade), and you'd be screwed.<br /><br />And there you have it, a code barricade.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com2tag:blogger.com,1999:blog-25340877.post-82588300626749450862009-07-07T20:35:00.008-07:002009-07-07T21:32:11.490-07:00When to use Class Inheritance in ProgrammingLast week I listened to a friend of mine complain about some straight-out-of-college programmers he had recently hired: "All of their code has 10 layers of inheritance. It's crazy trying to maintain their code!".<div>Unfortunately my friend is right: inheritance, although powerful - when used correctly, naturally tends to increase complexity.</div><div><br /></div><div>Since your primary purpose as a programmer is to manage and reduce complexity, you should favors solutions that don't use inheritance. </div><div><br /></div><div>At this point you're probably asking yourself: When am I supposed to use inheritance? How do I know if I'm using it correctly?Fortunately, the great Steve McConnel, has written 4 clear cut rules on when to use inheritance and when to use containment:</div><div><blockquote>1. If multiple classes share <b><i>common data but not behavior</i></b>, create a common object that those classes contain.</blockquote><blockquote>2. If multiple classes share <b><i>common behavior but not data</i></b>, derive them from a common bases class that defines the common routines.</blockquote><blockquote>3. If multiple clses share <b><i>commond data and behavior</i></b>, inherit from a common base class that defines the common data and routines.</blockquote><blockquote>4. Inherit when you want the base class to control your itnerface; contain when you want to control the interface.<br /></blockquote></div><div><br /></div><div>In summary, only inherit if the new class truly <i>is-a </i>more specialized version of the base class. </div><div><br /></div><div>Oh, and one more piece of advice on inheritance: avoid <i>multiple </i>inheritance like the plague.</div>Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com1tag:blogger.com,1999:blog-25340877.post-23882953750917194232009-06-15T19:12:00.007-07:002009-06-15T20:10:34.634-07:00How To Write Reusable Software: A Lesson From LEGO BlocksI don't know about the places where you have worked, but where I've worked we haven't had a very good track record for writing code that actually gets re-used. In fact, at one place we even gave up: "Software reuse is overrated" a boss muttered once.<br /><br />I think the reason we fail so miserably is that we focus too much on the end goal (reusable code), and too little on the qualities that make software reusable. What, then, are the properties of reusable code? Well, that's where the LEGO blocks part comes in.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Lego_Color_Bricks.jpg/800px-Lego_Color_Bricks.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 800px; height: 536px;" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Lego_Color_Bricks.jpg/800px-Lego_Color_Bricks.jpg" alt="" border="0" /></a><br />The LEGO block analogy comes from David West's <span style="font-style: italic;">Object Thinking</span>, but I'd like to highlight a few ideas that make this metaphor so applicable to software development:<br /><ul><li><span style="font-weight: bold;">The interface is simple and intuitive. </span>I've seen my 3 year old daughter build ships with LEGOs. If you want your code to be reused, it should be so simple and so intuitive that others could use it without having to refer to external documentation.</li><li><span style="font-weight: bold;">There's a finite and small number of LEGO block types.</span> If you find that your library has a high number of classes, think about what you are doing. After all, everything on this planet is made from the same 92 (naturally occurring) elements.</li><li><span style="font-weight: bold;">LEGOs are cool because you can build stuff.</span> The reason everyone loves LEGO blocks is because they can build whatever they want with them, not just what the box tells them to build. Your software should be the same way; you should be surprised by what end users build with your code. If your code only gets used for what you envisioned, you've failed to write reusable code: people are not able to <span style="font-style: italic;">compose</span> software with your code.</li></ul>Finally, don't forget that people don't really care about the technical details behind LEGO blocks; no one cares how the plastic is molded, dyed, etc. LEGO blocks aren't reused because of how well they're manufactured; they're reused because they let end users accomplish their goals.<br /><br />Once people are able to accomplish their goals with your code, they'll be using it over and over gain. Guaranteed!Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com2tag:blogger.com,1999:blog-25340877.post-27880374155568711032009-06-09T08:03:00.000-07:002009-06-09T08:04:10.404-07:00Custom Thousand Separator In C#I guess the NFA requires us to use a space (" ") instead of a comma (",") as our thousands separator. I dunno why the have to regulate something like that, but I had to figure out an elegant way to format our numbers the way the powers that be require them to be formatted.<br /><br />After struggling with different inelegant solutions for a little while, I finally realized that different countries use different symbols as thousands separators; I knew then that my problem was really a localization problem. A quick search in MSDN lead me to the <a href="http://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.aspx">NumberFormatInfo</a> class, which "defines how numeric values are formatted and displayed, depending on the culture" (MSDN).<br /><br />The NumberFormatInfo class, has a <span style="font-weight: bold;">NumberGroupSeparator</span> property that defines what character to use to separate thousands.<br /><br />So, here's how I ended up solving my problem:<br /><pre name="code" class="csharp"><br />public void FormatDouble(double doubleToFormat)<br />{<br /> NumberFormatInfo nfi = new CultureInfo("en-US", false).NumberFormat;<br /> nfi.NumberGroupSeparator = " ";<br /> Write(doubleToFormat.ToString("n", nfi);<br />}<br /></pre><br />Neat, huh?Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com2tag:blogger.com,1999:blog-25340877.post-69944776180826193872009-03-24T17:22:00.014-07:002009-03-24T18:09:11.675-07:00Highly Parallel LINQ To Lucene IndexerI've been wanting to post about this for a while, but haven't been able because I was away vacationing in Hawaii. :)<br /><br />I was recently given the assignment to index a couple of our tables that hold large amounts of data. Each tables has well over 3 million records, and each record is fairly large as it represents "emails" with our clients.<br /><br />I knew from the get-go I'd have to write a highly parallel process in order for the task to finish promptly - just bringing the data over the wire from the database takes about 45 minutes.<br /><br />I have to show a lot of code now, so please bear with me for just a second. The key here is to use several RamDirectory(s) for the small data chunks and merge them into a FSDirectory index that will hold all the data:<br /><pre name="code" class="csharp"><br />namespace Indexer<br />{ public class BatchIndexer[T] : ParallelIndexer[T]<br /> {<br /> IQueryable[T] items;<br /> bool isMergingFinished = false;<br /> private static object lockObject = new object();<br /><br /> public override bool Stopped<br /> {<br /> get<br /> {<br /> var pstopped = base.Stopped;<br /> if (pstopped == true)<br /> {<br /> return isMergingFinished;<br /> }<br /> else<br /> {<br /> return false;<br /> }<br /> }<br /> }<br /><br /> //stop setting the temp directory here and force the client to pass it in<br /> public BatchIndexer(string path, IQueryable[T] items)<br /> : base(new Index[T](path))<br /> {<br /> this.items = items;<br /> QueueChildren();<br /> }<br /><br /> private void QueueChildren()<br /> {<br /> if (null != items && items.Count() > 0)<br /> {<br /> const int pageSize = 100;<br /> int pageIndex = 0;<br /><br /> var currentPage = items.Take(pageSize);<br /> int pageCount = 1 + items.Count() / pageSize;<br /> while (pageIndex < pageCount)<br /> {<br /> ThreadPool.QueueUserWorkItem(new WaitCallback(QueueChild), currentPage);<br /> pageIndex++;<br /> currentPage = items.Skip(pageIndex * pageSize).Take(pageSize);<br /> }<br /><br /> //wait for all children to be added to parent<br /> while (Children.Count() < pageCount)<br /> {<br /> Thread.Sleep(2000);<br /> }<br /> }<br /> }<br /><br /> private void QueueChild(object stateInfo)<br /> {<br /> var currentPage = stateInfo as IQueryable[T];<br /> lock (lockObject)<br /> {<br /> AddChild(new BatchIndexerChild[T](new Index[T](), currentPage.ToList()));<br /> }<br /> }<br /><br /> public override void Run()<br /> {<br /> //start indexing the children<br /> foreach (var item in this.Children)<br /> {<br /> var child = item as BatchIndexerChild[T];<br /> ThreadPool.QueueUserWorkItem(new WaitCallback(child.AsyncRun));<br /> }<br /><br /> //wait for all of the children to finish indexing<br /> while (!IsChildrenStopped)<br /> {<br /> Thread.Sleep(1000);<br /> }<br /><br /> //merge all indeces into main index<br /> this.Merge((from c in this.Children select c.Index.Directory).ToArray());<br /> isMergingFinished = true;<br /> }<br /><br /> protected override void Dispose(bool disposing)<br /> {<br /> base.Dispose(disposing);<br /> if (disposing)<br /> {<br /> //release managed resource<br /> if (this.Index != null)<br /> {<br /> this.Index.Dispose();<br /> }<br /> }<br /> }<br /> }<br />}<br /></pre><br />I particularly like the approach I used because it threads the chunking of the data into smaller pieces AND is also threads the actual indexing of each chunk.<br /><br />If you're going to index as much data as I had to index, however, you still have to pre-chunk the data and feed into several instances BatchIndexer; I found that 100,000 records was optima. You'll also want to make sure you release all database resources ASAP: you don't to be hogging a whole bunch of memory! <br /><br />Anyhow, I hope this code is useful... it should at least give you start in the right direction. Let me know if you have any questions.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com2tag:blogger.com,1999:blog-25340877.post-33171550870651974172009-02-22T19:54:00.003-07:002009-02-26T20:54:02.051-07:00Factory PatternAfter reading <a href="http://adotnetdude.blogspot.com/2008/03/refactoring-code-with-too-many.html">this</a> article, a reader recently requested that I show some sample code for the "factory" mentioned in the article.<br /><br />Before I give you some sample code, however, let me just write a few words about the Factory Pattern: As the pattern's name suggests, the Factory Pattern creates stuff. Specifically, "factories" create classes without coupling you to a specific instance of the classes it creates.<br /><br />Here is some sample code:<br /><pre name="code" class="csharp">public class CreditCardBase<br />{<br /> //this is the base class that all credit cards implement:<br /> //it could be an abstract class, or it could have some functionality;<br /> //it could also be an interface... whatever floats your boat.<br />}<br /><br />public static class CreditCardFactory<br />{<br /> public static CreditCardBase GetCreditCard(object someObject)<br /> {<br /> //business logic that returns correct credit cart type goes in here.<br /> if(someObject == "something")<br /> return new Visa(); //visa of course implements CreditCardBase<br /> else<br /> return new Amex(); //also implements CreditCardBase<br /> }<br />}<br /><br />public class CreditClassClient<br />{<br /> //this class consumes a credit card<br /> public void DoWork()<br /> {<br /> CreditCardBase myCreditCard = CreditCardFactory.GetCreditCard(new bizObject());<br /> //do stuff with myCreditCard<br /> myCreditCard.Run();<br /> }<br />}<br /></pre><br /><br />And there you have it. That's pretty much all there's to it, and the code is pretty self explanatory.<br /><br />There's one more thing that's worth mentioning: usually, classes returned by factories have private constructors - to avoid people instantiating the class without calling the factory. This, however is problematic for several reasons:<br /><ol><li>You may have clients that already instantiate your class.</li><li>People usually make private constructors singletons (please don't).</li><li>How do you extend a class that has a private constructor? :)</li></ol>Finally, to the anonymous reader that asked for the factory code: let me know if this was useful.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0tag:blogger.com,1999:blog-25340877.post-31175107264366097932009-02-10T21:50:00.001-07:002009-02-10T21:51:06.026-07:00How Not To Lose Money In The Stock MarketOne of the most important rules to remember when investing in the financial markets is to <span style="font-weight: bold;">Preserve Your Capital!</span> Not losing money is the first step before you can <span style="font-style: italic;">make </span>any money.<br /><br />And although I haven't figure out a technique that guarantees 10% yearly gains, I have figured out a pretty good technique for not losing money in major market draw downs. Allow me to show you a chart of one of the <a href="http://en.wikipedia.org/wiki/Exchange-traded_fund">ETFs</a> I like to use to trade:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_U0AuZcqOces/SZIvEn5nVkI/AAAAAAAAAFg/fawGHTkpO10/s1600-h/qldMA.JPG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 181px;" src="http://2.bp.blogspot.com/_U0AuZcqOces/SZIvEn5nVkI/AAAAAAAAAFg/fawGHTkpO10/s400/qldMA.JPG" alt="" id="BLOGGER_PHOTO_ID_5301351467845113410" border="0" /></a><br />The chart to above shows the daily price for QLD, along with the 50-day exponential moving average (in red) and the 10-day exponential moving average (in blue). At the bottom of the chart, you can also see the daily trading volume.<br /><br />What's interesting in the QLD chart is that during the past year every major market drop has been preceded by a clear signal: the 10-day EMA crosses the 50-day EMA (heading down, of course). And this, even when the market has faced major volatility and huge daily drops.<br /><br />You can go back as far as you like, and you'll find that the signal above always hold true. And this is not because I'm so awesome and I've figured out some magic formula - no, it holds true because of the very definition of <a href="http://www.investopedia.com/terms/e/ema.asp">EMA</a>. The EMA lines just show you the averages of the stock price for the last 50 and 10 days respectively.<br /><br />Of course this technique isn't perfect: you will lose <span style="font-style: italic;">some </span>money before the 10-day EMA crosses the 50-day EMA; but at least you won't lose more that 50% of your money, like several people have in the past year.<br /><br /><span style="font-style: italic;">Disclaimer: </span>Don't take financial advice from a guy that writes software for a living (i.e. me). Also, don't take advice that makes a living selling financial advice (i.e. your financial advisor). Those guys don't make money in the markets; they make money making you feel good about losing 50% of your capital.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com1tag:blogger.com,1999:blog-25340877.post-34341930400895512942009-02-05T19:24:00.003-07:002009-02-05T19:52:53.241-07:00ASP.NET MVC Release Candidate Now Available!The release candidate for Microsoft's ASP.NET is finally <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=f4e4ee26-4bc5-41ed-80c9-261336b2a5b6&displaylang=en">here</a>.<br /><br />Sure, this is just another "me-too" Microsoft product: we've had Rails, Cake, and Grails - but this is great news nonetheless! The ASP.NET web forms model is one that I never really understood: Why would you try to imitate a windows form on the web? Anyhow, web forms have been long over-due for a replacement, and now MVC provides a great architectural pattern for building web apps with the .NET framework.<br /><br />Scott Gu, has written and in-depth <a href="http://weblogs.asp.net/scottgu/archive/2009/01/27/asp-net-mvc-1-0-release-candidate-now-available.aspx">article</a> describing some of the most important improvements on this RC. And, from what Phil Haack said on his <a href="http://haacked.com/">blog</a> about this release, I get the feeling there's just a few minor bugs that need to be addressed before the RTM. You could probably start using the RC now without any concerns. In fact, I have a co-worker that has been writing a site on MVC since beta with no problems at all. Another co-worker mentioned to me today how much more productive he was under the MVC model than the WebForms model.<br /><br />If you're still unsure about ASP.NET MVC, go check out <a href="http://stackoverflow.com/">stackoveflow.com</a>. StackOverflow was written on the beta release of the MVC stack, and it's an awesome site.<br /><br />Now, if you're still unsure, just trust me on this one: put your WebForms on the ground, back away slowly! I don't want anyone getting injured here. :)Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com1tag:blogger.com,1999:blog-25340877.post-45993781545047334032009-01-26T16:33:00.006-07:002009-01-27T19:19:16.911-07:00Software Engineering: There's nothing like it!<h3>Intro</h3><br />Seriously, there's no other type of engineering like software engineering. And that, may or may not be a good thing: it just depends on what you decide to focus on.<br /><br />I went to school in the same building where the mechanical engineers, chemical engineers, and civil engineers went to school - yes, I spent almost every waking hour of my college life in the infamous <a href="http://www.et.byu.edu/college_facilities.htm">Clyde Building</a>:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_U0AuZcqOces/SX5P-ag8RcI/AAAAAAAAAFI/3LfiWH56Di0/s1600-h/clyde.gif"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 187px; height: 150px;" src="http://2.bp.blogspot.com/_U0AuZcqOces/SX5P-ag8RcI/AAAAAAAAAFI/3LfiWH56Di0/s400/clyde.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5295758145522255298" /></a><br />Yes, for those of you that are wondering, that building has no windows. I'm pretty sure they designed it that way so that your soul would be crushed within the first semester of your career. But that's beside the point: You want to know what I learned in 4 years as an EE at BYU? Well, for the most part, I learned a whole bunch of math... oh yea, and I also learned that writing software isn't like making bridges, roads or "stuff".<br /><br />And here's why software enginnering is so different: <span style="font-style:italic;">software is cheap</span> to make (Yeah, that's right; even though you think you're making big bucks by writing software, you're still cheap compared to what goes into creating a new car design). Oh, and there's something else: <span style="font-style:italic;">writing software is much harder than building bridges</span>.<br /><br /><h3>Software is hard</h3><br />See, we can't really prove software will "work". Proving that a program will work according to the specs is pretty much a <a href="http://en.wikipedia.org/wiki/Halting_problem">halting problem</a> - that is, given a program and a finite input set, we can't even prove whether the program will even terminate!<br /><br />Civil engineers, on the other hand have it easy: given a bridge and environment conditions (load, winds, etc.), they can tell you whether the bridge will stand or not. In fact, it's so easy to "model" bridges that we software engineers have written programs to tell you whether you've built a good bridge or not.<br /><br />Software is also harder because as long as the program "works", it doesn't matter what the source code may look like. Sure, some code may be harder to maintain than other, but how do you tell? There's no metrics for code design; we only have <a href="http://en.wikipedia.org/wiki/Code_smell">smells</a>.<br /><br /><h3>Software is cheap</h3><br />Let's not move on to why software is cheap. If you write a program that doesn't work according to specs, it's not a big deal: you just go back to Notepad, change a little bit of text and (perhaps) recompile. Even software distribution is cheap: when was the last time you got software in a CD? We could spend a lot of time and effort finding bugs and/or proving our program works correctly, but why would we do that? After some point, it really doesn't make sense to spend money finding and solving bugs that may never surface in normal use.<br /><br />On the other hand, if you screw the pooch on a bridge you're toast: it's hard to fix, and it was really expensive to build (not to mention how much time it actually take to build). This is why civil engineers, plan, model, test and then finally, after a really long time, build. We just build because it's fast to build. How awesome is that?!<br /><br /><h3>Conclusion</h3><br />Now you know why you're much better than all those other engineers out there. So go rub it in their faces whenever you feel like it. :pAnonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com1tag:blogger.com,1999:blog-25340877.post-40530046469589916982009-01-23T09:42:00.002-07:002009-01-23T10:10:19.221-07:00What do programmers do?Have you been ever asked what you do for work? I have, and it's always hard for me to answer: if I say I'm a computer programmer people immediately think I can fix their printer - or worse, they want me to build them a dating website for five hundred bucks.<br /><br />The truth is that what we "computer scientists" do is more along the lines of what sorcerers do. <a href="http://groups.csail.mit.edu/mac/users/hal/">Hal Abelson</a> describes it really well:<br /><br /><blockquote>Computational processes are abstract beings that inhabit computers. As they evolve, processes manipulate other abstract things called data. The evolution of a process is directed by a pattern of rules called a program. People create programs to direct processes. In effect, we conjure the spirits of the computer with our spells.<br /><br />A computational process is indeed much like a sorcerer's idea of a spirit. It cannot be seen or touched. It is not composed of matter at all. However, it is very real. It can perform intellectual work. It can answer questions. It can affect the world by disbursing money at a bank or by controlling a robot arm in a factory. The programs we use to conjure processes are like a sorcerer's spells. They are carefully composed from symbolic expressions in arcane and esoteric programming languages that prescribe the tasks we want our processes to perform.<br /><br />A computational process, in a correctly working computer, executes programs precisely and accurately. Thus, like the sorcerer's apprentice, novice programmers must learn to understand and to anticipate the consequences of their conjuring. Even small errors (usually called bugs or glitches) in programs can have complex and unanticipated consequences.<br /><br />Fortunately, learning to program is considerably less dangerous than learning sorcery, because the spirits we deal with are conveniently contained in a secure way. Real-world programming, however, requires care, expertise, and wisdom. A small bug in a computer-aided design program, for example, can lead to the catastrophic collapse of an airplane or a dam or the self-destruction of an industrial robot.<br /><br />Master software engineers have the ability to organize programs so that they can be reasonably sure that the resulting processes will perform the tasks intended. They can visualize the behavior of their systems in advance. They know how to structure programs so that unanticipated problems do not lead to catastrophic consequences, and when problems do arise, they can debug their programs. Well-designed computational systems, like well-designed automobiles or nuclear reactors, are designed in a modular manner, so that the parts can be constructed, replaced, and debugged separately.<br /></blockquote><br /><br />Although I'm attributing the quote to Abelson, the text above comes from the book <span style="font-style:italic;">Structure and Interpretation of Computer Programs</span>, written by Albeson, Sussman, and Sussman. The reason I'm attributing the quote to Albeson is because I first came across this by watching one of his MIT lectures on the same topic. <br /><br />If you're interested in watching MIT's introductory "Structure and Interpretation of Computer Programs" class, you can find the videos <a href="http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/">here</a>.<br /><br />And now, go conjure some spirits!Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com2tag:blogger.com,1999:blog-25340877.post-57311019295345107422009-01-15T19:26:00.005-07:002009-02-01T18:42:15.399-07:00The Perils of Sushi Bars<span style="font-style:italic;">This is the story of how my credit card was almost stolen by a Samurai in a sushi bar in Salt Lake City. If you're interested, read on.</span><br /><br />About 2 months ago I went to a sushi restaurant here in Salt Lake City. After paying our bills and while we were walking out, Kevin (one of my co-workers) noticed that his receipt had his full credit card number printed on it. Rightly concerned, he immediately talked with the restaurant's manager and asked to see the restaurant's copy of his receipt - sure enough, the restaurant was storing hundreds of credit card numbers in their little dinky cash register.<br /><br />The whole incident got me thinking about credit card transactions. Every time I buy something with a credit card it's like I'm handing my wallet over to the clerk and saying: "Here's my wallet. Take whatever you need and just hand it back when you're done." Who knows what the POS machine is doing with my credit card number! And that's the least of my concerns: What about the lame payment gateway that stores millions of credit card numbers on servers that will likely be hacked in the next 5 years?<br /><br />Interestingly enough, however, the whole credit card thing seems to work remarkably well. I mean, there's little risk in the sushi bar overcharging; after all, I know where they're at, and I also have the the credit card company on my side: one call to the them and the restaurant we'll have to pay the bill. As far as the payment gateway is concerned, even thought there's the PCI standard, when they get hacked we all pay the cost (either thorough higher interest rates, more taxes, etc)... that's why I'm really concerned about them - I worked at a place where we were PCI compliant, but there were still gaping holes in our security model.<br /><br />This particular sushi story, however, has a happy ending. We recently went back to the restaurant and were pleasantly surprised to see that our full numbers were no longer being printed on receipts. It's good to see that non-IT folks are finally starting to get the importance of securing information.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0tag:blogger.com,1999:blog-25340877.post-63202617979041378052009-01-08T18:38:00.000-07:002009-01-08T18:35:58.314-07:00Steve Yegge Is My HeroI regularly read <a href="http://joelonsoftware.com">Joel Spolky's blog</a>, <a href="http://codinghorror.com">Jeff Atwood's blog</a>, and <a href="http://steve-yegge.blogspot.com">Steve Yegge's blog</a>. I really like them all, but Steve's is probably the most thought provoking blog out of the three.<br /><br />Recently, for example, he had a post where he discussed (at length), a very intersting topic:<br /><br />Imagine Mario, and his brother Luigi, having a conversation in which Mario asks Luigi what's on the other side of the boundary to their <a href="http://www.amazon.com/gp/product/B001AU6W10?ie=UTF8&tag=theramblofane-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B001AU6W10">Mario Kart</a><img src="http://www.assoc-amazon.com/e/ir?t=theramblofane-20&l=as2&o=1&a=B001AU6W10" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /><br /> universe. Interesting, huh?<br /><br />It's interesting because to Mario & Luigi, stuff on the "other" side of their universe boundary is "undefined"; it's undfined in the sense that anything could be there. In fact, to some extent, it doesn't even make sense for them to ask what's on the other side; they simply cannot define what's on the other side as long as they reside inside the Mario Kart universe.<br /><br />On the other hand, programmers living outside the Mario Kart universe can easily define what's outside the Mario Kart universe: all they have to do is inspect the memory contents of the system running Mario Kart, and take a peek at what's in there, on the "other" side.<br /><br />I enjoyed Steve's post on <a href="http://steve-yegge.blogspot.com/2008/12/programmers-view-of-universe-part-2.html">embedded systems</a>because it helped me make sense of the embedded system I live in. I now understand that anything could be out there; it's truly undefined.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0tag:blogger.com,1999:blog-25340877.post-38581766082406429972009-01-08T16:32:00.006-07:002009-01-08T17:37:55.913-07:00Lucene.net UnAuthorizedAccessExceptionUnless you specifically tell Lucene.net where to put its LOCK files (for the index readers and writers), it will put them in your OS's default temp directory (normally C:\Windows\TEMP\). This choice of location may be problematic.<br /><br />As you can imagine, there are plenty of scenarios under which Lucene.net may be running under an identity that does not have enough to access to your temp directory. Under such scenarios, you'll get an UnAuthorizedAccessException thrown at you; and your code may not even be around to handle it.<br /><br />To solution for this problem is easy; add the following to the <appSettings> section of your application's config file:<br /><br /><pre name="code" class="xml"><br /><add key="Lucene.Net.lockdir" value="C:\SomeFolderOfYourChoice" /><br /></pre><br /><br />After doing this, make sure "Everyone" has full control of the folder you've chosen for Lucene.net to use as its LOCK file folder.<br /><br />You should also consider properly disposing your indices when your process finishes so that all locks are release on a timely basis. Unfortunately, I can't tell exactly how to do that - you'll just have to figure it out.<br /><br />Finally, if you're reading this for some other reason than having the exception thrown at you, you should really consider using Lucene. It's great!Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0tag:blogger.com,1999:blog-25340877.post-42105241846393050842009-01-06T17:20:00.003-07:002009-01-06T17:46:04.696-07:002008 ReflectionsMan, it feels good to be back to blogging! It was an awesome Christmas break, but I must admit I kept coming up with ideas I wanted to blog about.<br /><br />Anyhow, '08 was a great year for me: I moved to a great <a href="http://ibfx.com">company</a> and started blogging regularly. I also learned a lot of LINQ, some Ruby, and had some great personal moments.<br /><br />As a recap of 2008, I wanted to share my favorite posts so far:<br /><a href="http://adotnetdude.blogspot.com/2008/12/secret-behind-linq-to-sql.html">The Secret Behind SQL</a><br /><a href="http://adotnetdude.blogspot.com/2008/11/easy-background-tasks-in-aspnet.html">Easy Background Tasks in ASP.NET</a><br /><a href="http://adotnetdude.blogspot.com/2008/10/why-partial-classes-are-wrong-and-why.html">Why Partial Classes Are Wrong!</a><br /><br />I also wanted to thank all of you that regularly read my blog. There's a few of you out there that are loyal readers, checking often whether I have new content or not; knowing that you're reading makes me much more critical of what I write. Thanks for your time!<br /><br />Finally, here's and interesting graph of traffic on this blog:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_U0AuZcqOces/SWP5mj5LfjI/AAAAAAAAAFA/yLHR96HRytk/s1600-h/traffic.JPG"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 109px;" src="http://3.bp.blogspot.com/_U0AuZcqOces/SWP5mj5LfjI/AAAAAAAAAFA/yLHR96HRytk/s400/traffic.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5288344828328508978" /></a><br /><br />You see that spike right around Nov. 17th, 2008? That, my friends, comes from <span style="font-style:italic;">one</span>small comment buried among hundred of comment's in Jeff Atwood's <a href="http://codinghorror.com">blog</a>. Isn't that crazy? That blog is the black hole of developer effort; I swear every developer on planet earth goes there to waste their time... I can't find any other explanation for getting so much traffic from just one comment. Thanks Jeff! And thanks to everyone that followed the link and took time to read what I had to <a href="http://adotnetdude.blogspot.com/2008/11/how-to-be-better-programmer.html">say</a>.<br /><br />May 2009 be a great year for you.Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0tag:blogger.com,1999:blog-25340877.post-24069186340505183112008-12-19T15:17:00.003-07:002008-12-19T21:37:02.689-07:00Why You Should Be ControversialI have to tell you a story before any of this makes sense, so bear with me for a minute.<br /><br /><a href="http://murrayon.net/">Michael Murray</a>, a good buddy of mine, IMed me today telling me he had been invited to write a blog post for the the main page of <a href="http://tech.lds.org/">tech.lds.org</a>. I was really happy for him; he deserves it as a tribute to his tireless contributions to the LDS tech community.<br /><br />Unfortunately, for reasons that I can understand, Mike was having a hard time coming up with what to say. I mean, there's tons you could say, but you have to be somewhat careful... after all some may mistake criticism of the software the LDS Church employees write with criticism of the LDS Church period. And then there's also the fact that Mike really cares about the tech.lds community; he's an active moderator in it.<br /><br />Unfortunately, the tech.lds community suffers from the same problem any extremely homegenous community does: everyone says the same freaking thing all of the freaking time! Everyone talks about how IT is a means to an end; everyone talks about how we, as IT folk, should seek for way to further the Kingdom and be more wise servants. Please don't get me wrong: I know that what the tech.lds community preaches is true, but haven't we heard enough of that already?<br /><br />Why don't we talk about some of the real issues with IT at the Church?<br /><br />Here's a few ideas off the top of my head:<br /><ul><li>How come LDS software is not open sourced? I still remember when I helped build my chapel back in Ecuador; truly a memorable experience - it was great to be able to contribute beyond tithing money. </li><li>How come phone numbers are tied to households in MLS? What's up with that?!? And even more important, how come that wasn't fixed 10 releases ago?</li><li>How come the IT department used to pay terrible salaries to IT employees? I recognize this is changing, but what kind of people was the IT department expecting to hire?</li><li>Why did it take 10 years for meetinghouses to get broadband internet access? Did IT managers really just learn of white lists?<br /></li><li>Why does it take days to transfer membership records into a ward? Isn't it just a simple look up? And if it's not just a simple look up, how come it's not?</li><li>Why is the Church developing on the Java stack? When was the last time you saw MLS running on a Linux box?<br /></li></ul>I've been deliberately controversial on this post because I wanted to make point: if you're going to say something, you might as well say something that's worth thinking about. I suspect there are good answers to all of the questions I've listed above; furthermore, I realize in the grand scheme of things I know nothing compared to what the fine folks at the LDS Church do. But at least, you read this far and know you're thinking about software at the Church too.<br /><br /><span style="font-style: italic;">Disclaimer: I cannot say it more clearly than this: I'm criticizing IT at the LDS Church, I am NOT criticizing the Church of Jesus Christ of Latter Day Saints. To some extent, I'm not trying to criticize the folks the work in IT at the Church; I realize that were I in charge of IT things would probably be even worse than they're now.</span>Anonymoushttp://www.blogger.com/profile/07645289431023957896noreply@blogger.com0