• The Lemonade Dilemma

    Once you have a software company, your product will inevitably change. It will probably change based on many factors, but most notably it will change to the benefit of customers who have the most money and/or customers who complain the loudest and most often.

    I have this Greek place that I go to fairly often with my wife. They, for as long as I have been going there, have always served lemonade similiar to their iced tea. In a large free pour container, from which I can assume was probably "Country Time" or some other powder lemonade mixed with water and maybe sugar. it was usually room temperature and melted quite a bit of ice nicely and just had a perfect flavor to me. No it wasn't fresh squeezed lemonade, but it was the drink I almost always had when I went there. For the longest time, I have been completely satisfied with my service.

    We went there a few weeks ago, and they had replaced the lemonade with a fountain drink lemonade... Minute Maid. Now, I'm not exactly anti-Minute Maid, but Minute Maid is the kind of lemonade that kids drink. It's the sort of sugary sweet, kool-aid-esque, syrup-y thick lemonade that you can get at just about every place in the rest of the city. I was a little disappointed... admittingly, I was verbally annoyed. Well, I let it go and a few weeks later, we went back. I had completely forgot they had ditched the favored lemonade until I walked in the door.

     

    I asked the manager, "Sir, why the change in Lemonade"

    He replied, "Well, we just had people complain all of the time that we didn't have Minute Maid, and the other just wasn't as popular"

    "Fair enough" I said.

    Now, I am honestly over the lemonade switch, despite how hard it is to tell by this story. However, I was thinking about it today and discussing it with a friend. I can think back to numerous software companies making this type of choice. They seemed to stop responding the careful analysis of the cost, profit, and existing customer satisfaction based on the way their software operated and followed the forum complaints, support tickets, and general badgering into a new way of doing things.

    My first experience with this was Ultima Online. A tragic quality blunder, but that's actually not what I am going to speak of. UO was openly PVP enabled. This meant that anyone at any time could kill anyone, anywhere (Except in towns and other certain rare special safe havens). However, as time went by, people complained and complained and some probably quit playing too. Point is, MANY people stayed around. Those people were barely considered when the game was split into two different new 'worlds'... one that was 'free pvp' and one that was 'completely safe'. Admittingly, the fun in the game for me was taking on unsuspecting travelers and such as a bandit (on one of my characters) and also playing the other side as a vigilante for justice (Anti-PK, they called them, or 'Antis' for short).

     

    My second experience with this was Planetside. The game had a great beta. It was one of the most amazing games I had ever played. I was in love with driving around a tank while my close friend, Mike, ran the large cannon. We would weave in and out of trees, bases, and over and around hills using our rapid speed and maneuvering to run over almost any ground troops and powered armors while Mike blasted larger targets like tanks and vehicles with the cannon. Well, people complained... instead of using cover, vehicles, teleports, or the other thousands of options they had at their disposal, they simply complained that tanks were too over powered because they could run over people so easily. Well the giant nerf bat came down on tanks hard (a term lovingly used to refer to a 'softening' of a game feature to accomodate weaker players). They made it so that each person you ran over slowed down your tank CONSIDERABLY and powered armors brought your tank to a complete stop. It was absurd. They took it way too far and made the tank completely useless on the battlefield because people would throw themselves in front of it to stop the tank so everyone could hit it with dumbfire missiles.

     

    My third experience with this was another SOE game, Star Wars Galaxies. I played from beta in this game as well and we had nurtered and built the game up as a community of beta testers to what we saw as a new social gaming success. A game that females would get into, a game that casual players could get into. It had a plethorae of non-combat options to get everyone involved. It wasn't just another medieval AD&D rip-off. Well, then  World of Warcraft came out and just sold so many copies. The leadership of galaxies ruined the game by tweaking and tweaking and removing everything that had made the game what it was. Eventually the game utterly failed and is scheduled to be canceled and deleted. Frankly, I am glad.

     

    One thing I have seen commercial products do, which is probably admirable to an extent, is the idea of configurability. one thing that I learned from Jez Humble in "Continuous Delivery" and from seeing it in practice is that Variants (or branching) is a bad thing! It brings development to a grinding halt or such a bad slowdown that you can hardly get anything done. Another reason that this configurability (while good intentioned) is bad is because the more complex it gets to configure your product the more you have to create "professional services" departments to configure it for your customers and the further and further you silo yourself in to being the only experts in your solution. An optimal product is a solution. It is something that is easily configurable, runs out of the box, and can be used by and supported by the densest (or just mediocre-est) of IT departments. Let's face it... look around at IT departments :) they're degrading badly :)

     

    Anyhow, I think I have sufficiently smashed enough nuts in this post so I will move on now. Remember, keep your software focused, keep it clean, keep it easy to configure, and stay true to the original solution. If people complain... take it to heart, but don't change the core of your product if it means sacrificing your existing customer base and their satisfaction.

     

     

     

    Full story

    Comments (0)

  • Automated Deployment Lessons Learned

    We have this ETL/Datawarehouse project going on at work and it uses these windows scheduled tasks to go grab data out of web services and import them into our database. There's nothing very interesting about that particular process however, deployment is always frustratingly manual and annoying because you have to update these scheduled tasks and copy the console applications and then modify config files.

    My first charter was to get every console app using the same file for connection strings. That's actually pretty easy, you just use <connectionStrings configSource="yourNewFile.config">

    You can check that out over here:

    http://stevenharman.net/blog/archive/2007/06/07/tip-put-connection-strings-in-their-own-configuration-file.aspx

     

    You create one single file for the connection strings then you add it to each of the projects that use it by using 'add as link' in the add new item dialog box. 

    The second step was creating a windows installer with a custom action. That's a bit more tricky... I found the steps of how to do that

    http://msdn.microsoft.com/en-us/library/d9k65z2d(v=VS.100).aspx#Y231

     

    The last thing I did was have to learn how to use the scheduled task COM+ API... here's where I read about it:

    http://www.infoq.com/news/2008/02/TaskScheduler

     

    There are some references on MSDN about it... here's a short sample code that I created to get me started:

    public void CreateRepeatingIntervalTask(string userId, string userPwd, string appPath,

    string triggerStartDateUtcString, short triggerDaysInterval, TimeSpan repeatAfter, string taskName)

            {

                //interval doc:

                //The amount of time between each restart of the task. The format for this string is P<days>DT<hours>H<minutes>M<seconds>S

                //(for example, "PT5M" is 5 minutes, "PT1H" is 1 hour, and "PT20M" is 20 minutes).

                //The maximum time allowed is 31 days, and the minimum time allowed is 1 minute.

                if (repeatAfter.TotalMinutes < 1)

                    throw new ArgumentException("repeatAfter must be >= 1 minute");

                if (repeatAfter.TotalDays > 31)

                    throw new ArgumentException("repeatAfter must be <= 31 days");

                string repetitionMinutesString = string.Format("P{0}DT{1}H{2}M{3}S",

    repeatAfter.Days, repeatAfter.Hours, repeatAfter.Minutes, repeatAfter.Seconds);

                ITaskService scheduler = new TaskSchedulerClass();

                scheduler.Connect(null, null, null, null);

                ITaskDefinition task = scheduler.NewTask(0);

                IExecAction execAction = (IExecAction)task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);

                execAction.Path = appPath;

               

               

                IDailyTrigger daily = (IDailyTrigger)task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_DAILY);

                daily.StartBoundary = triggerStartDateUtcString;

                //http://msdn.microsoft.com/en-us/library/aa381138(v=VS.85).aspx

                daily.DaysInterval = triggerDaysInterval;

                daily.Repetition.Interval = repetitionMinutesString;

               

                daily.Repetition.StopAtDurationEnd = false;

                ITaskFolder folder = scheduler.GetFolder("\\");

               

                IRegisteredTask regTask = folder.RegisterTaskDefinition(

                    taskName,

                    task,

                    (int)_TASK_CREATION.TASK_CREATE_OR_UPDATE,

                    userId,

                    userPwd,

                    _TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN_OR_PASSWORD,

                    "");

            }

     

     

     

     

     

     

     

     

     

     

     

     

    Full story

    Comments (0)

  • Organizational Values as Anti-Patterns

    I like anti-patterns… so here are a few organizational values as anti patterns. See if you can tell what these people value. Where do you think they got this behavior? How is their behavior influencing the culture around you?

     

    Delegator

                “hey, can you call Mitch, his login isn’t working. That should only take you 15minutes.” This guy stands between you and your customers and delegates every request to you with no regard to your workload, capacity, or priority. Everything is Top priority to the delegator. He often tells you how long it will take you as if to imply it’s easy so you don’t tell him you don’t have time because you’re already working on his 4 other #1 priorities. Best Defense: Make delegator choose what you will drop to do his new item.

     

    Pizza-Buyer

    “Thanks for doing this war room, let’s buy you lunch so you don’t have to leave” Has a ‘go to’ motivational tool for everyone “pizza, time off, training-of-your-choice”. Thinks that you’ll eat dogshit and love it if she just rewards you now and then with mundane things like food or a leaving at 2pm. Best Defense  –  hate pizza

     

    The Appeaser

                “Wow that is the most interesting thing I’ve ever heard about SOLID principles and TDD, Bret… now so how about those TPS reports, how are those coming?” The appeaser thinks that if they just tell you how awesome all of your ideas are that you’ll just get back to doing the tasks they want you to do so they can get back to what they were doing.

     

    The Pomeranian (Shitzu, West Highland… etc)

                “Omg arf arf arf arf OMG arf arf arf!” The shitzu gets worked up when other people get worked up and it feeds straight down to you and is in your face. They often have a solution but never explain the problem to you. If you find yourself in a meeting with no idea why’re you’re there you’ve probably been a victim of the Shitzu.

     

    The Victim

                “Ted, you’ve always been able to save my butt before… can you help me?” The victim realizes that you’re a hero and you want to save people from burning buildings. They’ll use that to their benefit by making you out to be the hero… they’ll even give you credit for it and take you out for dinner. You’re team will hate you because you always shirk the team work for the hero work.

     

    The “Nice” Threatener

                “Bill, you like this manager job and having this office don’t you?” The threatener never says they’ll can you but they got stuff they want done… if you don’t do it… well there may be trouble ok. Not much you can do here… unless someone has bigger firepower than the threatener and can get your back.

     

    The “Gut” guy

                “Sure all that scrum and PMI and ‘planning’ stuff is interesting, but what does your gut tell you on this? You don’t want to be one of those academics!” Gut-Guy was probably once very educated but has become cynical since idealism gets tiresome. “This is the real world, man”. No amount of ‘best practices’ or outside proof will convince this person that they understand the context best and you should just go with your gut.

     

    The “Experience” gal

                “I’ve been doing this for 30 years [so whatever you just said I Ignored because I know better than you do] so let’s just do it the way I know works.” Experience gal is probably wrong, but 30 years of doing it wrong has never gotten her killed or fired so it must be the right way of doing it! Experience gal and Gut guy are interestingly at odds with one another… unless they’re the same person.

     

    The “Academic” Guy

                “well let’s see it says on page 94 that you just need to write the user story on a card and then we’ll write what we want to test on the back and then we’ll estimate it using these planning poker cards” Academic guy has read a lot of stuff… he’s probably smart and knows a lot of terminology but he doesn’t really understand how it fits together in ‘the real world’. He is almost certainly at odds with Experience gal and gut guy, but is insignificant and ignored because no one listens to intellectuals. Usually they have no idea why things are best practices… they just use them blindly.

     

    The Schmoozer

                “yea we’ll be doing your review soon, just give it some time. We need to talk to the president and push some numbers around.” The schmoozer is you’re best friend… I mean he hasn’t given you a raise in 2 years because “the economy is in the crapper” or “we haven’t had reviews yet” or “no one is getting raises”. There  is never an objective goal to get anything from Schmoozer.  He just has his schtick that he probably copies straight from his bosses mouth and he’s such a pushover he falls for it… but you’re not buying it… are you?

     

    The Carrot-Dangler

                “ok so here are your objectives for this year, you make a 5 star rating on all of these and you put you in for that promotion.” Carrot dangler hangs the awesome carrot in front of you and gives you all this great ‘objective’ stuff to do for him.. (mostly just cut and pasted from his bosses objectives for him). If you like hamster wheels or treadmills this can be kindof cool… usually the objectives are easy to pretend that you’ve done them. Honestly I’m good at working for a carrot-dangler I just realize it’s an endless wheel of making them more famous and popular while you’re tucked away in your cube hammering all these things out for them they’re out making good friends up the chain and getting promoted. If you want to work for the same guy forever that’s cool just make sure he’s actually going to becoming 1 pay grade higher than you wish to become.

     

     

    So… why am I talking anti patterns?

     

    Companies say they have “Values”… “Core values” or “Cultural values” or “Organizational values”

     

    We’ve all seen them… they’re in the handbook.. posted on walls… said in a cliché-like super-cool do-as-i-say-not-as-i-do tone by smooth looking chiseled featured CXO style muckity mucks.

     

    What are they really though?

     

    How can you tell what the real organizational values are at the company that you’re about to work at are?

    Full story

    Comments (5)

  • Some ways i handle email

    You can disagree with this stuff but this is how I (try to) roll:

    • Don’t put multiple people in the TO field.
      • If you absolutely must put multiple people in the TO field (so everyone knows what you told each person), then address each person specifically in bold and repeat any relevant details to them in what you say ‘to them’ in the email.
      • Don’t use BCC that’s like talking behind someone’s back.
        • If it accidentally gets a reply all you’ll look stupid.
        • If their boss needs to know then openly cc their boss.
        • Use bcc only if everyone in the email is BCC such as to keep everyone's email addresses private when others don't know the address.
          • such as some sort of external mailing like a joke to your internal and external friends (keeping everyones address private)
          • To share training opportunities so it's not like you're saying "Hey this person doesn't know this shit, laugh at them"
    • Don’t put multiple objectives in a single email.
      • People will read until they see a ‘relevant detail’ then stop reading.
      • If you have to do it, use bullet points so they realize there are multiple things to consider.
      • Don’t use bold or say ‘note’ people ignore that because they think it’s just more stuff relevant to what you just said. Usually people emphasis ‘additional details’ so if they already ‘get the gist’ they won’t read it.
      • Don’t have email signatures. Sorry they’re just annoying.
    • Don’t use a past email as a whip when people didn’t do what you expected them to. “WHAT? It was in the email I sent you last week! You remember: The one that had 15 things in it that weren’t bullet pointed and 12 of them were irrelevant to you.”
      • This goes for wiki pages and other documentation as well.
      • If you didn’t get an answer in the affirmative assume I didn’t follow the email. Emails are assumed lost unless confirmed.
    • Emails are assumed lost unless confirmed.
      • Yes it is worth saying twice J
      • A read receipt doesn’t mean someone read it.
      • A lack of read receipt doesn’t mean they didn’t read it
        • It might mean that person boycotts read receipts (like I do because it’s an intrusion and a false expectation that you actually communicated your email properly to me and that I understood any of it)
      • Firing off a round of emails doesn’t mean you’re off the hook from then on.
    • Following up on an email is YOUR responsibility. Not the recipient.
      • Set a reminder for X days out on your email to follow up and see if they got it and understood it.
      • Ask for feedback on the email if they didn’t understand
        • You might suck at communicating with this person so you need to get feedback and tailor your style.
    • Don’t save up a bunch of stuff to email at the end of the day in one big email.
      • No one wants 1 big email at 4pm they’ll ignore it.
      • If there is 1 single thing on that list that they can’t answer or do, they will not get back to you FOR ANY OF IT.
      • If people are annoyed with lots of tiny emails, it’s not because your emails are too frequent it’s because whatever you’re sending them is useless to them. Figure out which ones are useless.
    • Don’t reply all to your own email shortly after your first one
    • Don’t recall emails. Just reply all and correct yourself. Unless it was an unintentional very large reply all or large distro then just leave it alone and suffer your fate J
    • If there is a meeting where you will see the person… just wait. Save them the email.
    • If someone doesn’t understand your email and replies with a question. Call them or see them in person. Don’t reply to the question. If they already don’t understand you then they probably will get confused with your clarification. Just call them, straighten it out, figure out how to communicate better with them.
    • Use a good subject
    • makes sense in searches
    • short
    • is not ambiguous
    • does not ask a question (let the body do the talking or people will skip the content)

     

    Full story

    Comments (0)

  • How I Focus on Software Quality



    Quality software is Code that delivers the intended andconsequential business value while also keeping a minimal amount of maintenancecost after it’s delivered.

    Here is my recipe for successfully delivering this. Take it or leave it... seriously it's just how I personally do things and i'm definitely willing to hear some feedback just don't expect me to argue that there is one best way. This is just 'my' way... one of many possible ways.

    Acceptance Test Driven Development or Behavior DrivenDevelopment is the first step.

    Let’s take what everyone is familiar working on… a defect.Generally a customer experiences some sort of behavior and it is undesirable.They call in, they are pissed, they want you to make it work correctly forthem.

    Reproduce the issue. This is first and foremost… you can’tfix something you can’t see. Reproduce the issue and while you’re reproducingthe issue gather as much information as you can about what the root cause mightbe.

    Figuring out the root cause is something that I often have ahard time explaining to people. I generally think of finding root cause as similarto troubleshooting. First if you have a problem… divide the problem in half andsee where it follows. In the case of software… if you have multiple classes orcomponents in play try to isolate them with known working components or in aunit test harness/fixture.

    Reproducing the issue in a unit test with a debugger is asure-fire way to see what is going on that is wrong.

    Note: if you cannot figure out how to reproduce the issueand it’s only reproducing in a customer’s system then your first step should beto Create More Robust Logging around the problematic area. Debug loggingin  a production environment is essentialno matter how well you use TDD or ATDD and no matter how great your programmingability is. Just be careful not to break any privacy or data storage laws(things like credit card CCV2 for example are illegal to store)

    Once you can isolate the issue to a certain area of codethen you absolutely MUST identify what components need to change to fix theissue. (DO NOT FIX YET).

    This is like a level of effort examination. Inform yourtester what all you plan on changing. You know the person who has to determinewhat will need regression tested after you go fumbling around in the code.

    Programmer:Ahh yes package A, package G, class C, Class F,method G, method Z…

    Tester: oh really you have to change package G? I guess I willhave to regression test Foobar then.

    Create all the appropriate project level reporting stuff atthis point (tasks with estimates for example, in scrum)

    Now write unit tests for every class/method that you will beimpacting with this change. Use “Right BICEP” to test and refactor as needed toadd tests (See Working with Legacy Code)

    The whole time I’m doing new unit tests and refactoring, I amconstantly going back and checking things out in the UI to make sure that Ididn’t break anything. Follow as many paths through the code as you can (preferably100% of them). Some gui based automation could help here too.

    OK NOW fix the code using TDD.

    Re-run all the automated unit tests (including your new testthat checks the bug)

    Get a code review

    Refactor as needed

    Re-run automated unit tests

    Do user acceptance testing.

    Release to customer.

    Full story

    Comments (0)

  • Scaling Scrum with User Stories

        One of the more difficult things to understand for companies who are converting from non-agile methods to agile is figuring out how to convert their requirements and support pipelines into something that works for agile teams. If you're familiar with Mike Cohn's book "User Stories Applied" then some of this terminology will be familiar to you. If you're familiar with Scrum and user stories then hopefully this will communicate a more clear 'example' or 'starting point' for you to begin scaling agile practices across larger sets of development teams.

        The classic breakdown of work in a normal organization begins at the strategic office or PMO. They will often begin strategic planning very far in advance of the development teams creating a portfolio of programs that will turn into projects of specific tactical purpose.

        There are generally two camps from here out… those who would say that the PMO and program management acts the same as it did before and Scrum and/or Agile methods fit below that somewhere. The other camp, however, is where I sit. This is the camp that says "There are no secret backlogs, there are no dual backlogs, there is only 1 single enterprise backlog that everyone works from."

        The reason I am in this came is because an organization that focuses on it's highest priority goals succeeds rapidly in the marketplace by delivering it's highest value items first and rapidly responding to the feedback that they provide.

    That's my elevator speech for it anyhow.

    So what does that look like in practice?

        Well, at the top of this food chain you have products and themes. I generally just call this layer "Themes" but please keep in mind that Themes can span multiple products and a product can span multiple themes. That is to say if Microsoft office was a product and each "word, outlook, excel, and access" are themes and at the same time truetype fonts could be a theme across office, windows 7, and ms project. This complex relationship is important to keep open and flexible because it may require coordinating multiple products to deliver a particular theme (of functionality) and it may be required to coordinate multiple themes to create a single product.

        Under themes you have Epics. Epics are the classic "Minimum Valuable Feature" that a business or stakeholder can recognize. You'll usually recognize an epic when developers say "We can't deliver all of that in one sprint, it's too big, and the business person says "well it's just not deliverable unless I get all of it". A good example of an epic would probably be an initial set of Charting in Excel. You couldn't ship charting with just 1 type of bar chart for example. Careful here because epics can undeniably turn into themes very quickly if not constrained to a certain subset of minimal functionality to be releasable. As an example, if you just said "Charting" then that would be a theme. (In my opinion… but you be the judget because it's all about your context)

        Under Epics we have user stories. These are 'features' that are recognizable to some sort of actor in the system. (Or user if you prefer). I like to say actor because maybe you're building a web service to be consumed by mashups across the globe and your company will never be developing the client application that any end users will utilize. A user story is generally a finite piece of functionality that can be indepdent of other stories, negotiable in content (finite in scope), valuable, estimable, small (enough to fit many of them in an iteration if possible), and testable (or verifiable by the customer so that they know what they got). (INVEST is a simple way to remember this)

        Once you're at the team level you break this down to tasks (mostly technical tasks). Tasks are pretty straightforward… "make getter stored proc", "Make setter stored proc", "create DDL Script", "install sql server", "configure windows server and IIS7", "create build script", "Write end user documentation on widget x"

     

    So the tricky part here is… how do customers and stakeholders interface with the team to make sure they get what they want?

     

    Short answer… you need to decide that.

        Long answer. Identify your product owner(s): Maybe you have a particularly great customer who is willing to provide you a product owner to work directly with the team and create these artifacts. Perhaps you have that but they are unwilling to create user storiesl…. Those are just too indepth for them to worry about. So you might get a business analyst/user proxy who can create the user story level breakdown. That isn’t much different than writing requirements in many ways (just more real time with development). Perhaps your customers are internal to you and there are many of them. Find someone they trust who can represent them and have them act as your product owner. Perhaps there is a ‘director of product management’ who can be your top “Theme level” product owner. Then product managers would write epics and Business analysts would write user stories.

        The tricky part here to get right is support. How do you handle listening to support and involving their feedback. My recommendation is to make that the area product owner’s primary job. Afterall, keeping your current customers happy is the most important part of a good software practice. They generate revenue, they keep buying new upgrades, they promote your software to other users, they help other users support the product, and they create new ideas and innovation for you.

        This gives them direct contact with the person closest to the team so that if a high priority customer issue comes up you can properly abort the sprint and re-prioritize if needed. I've heard of some organizations just saving 1 team member's capacity solely for support issues every sprint rotate who that is. They can be support-bitch (or support-monkey to be more PC) and rotate it around each iteration. Maybe have a stuffed dog or monkey that signifies who is on support and put it on their desk when it's their turn. That person would work with the APO and Support to create a user story around the issue, create acceptance criteria, get sizing from the team once a solution is ready, then get it into a sprint as a user story once that prep work has been completed.

     

        Support bitch would probably not have time to also develop, test, and push out a hotfix though (but maybe if they're a rockstar, right?)

     

        If you have other ideas of how to scale agile out and up including examples from your organization please drop me a line or comment here. I appreciate your time and feedback.

     

    Full story

    Comments (0)

  • More on Fluent NHibernate (Lesson 2 for me)

     

    I started learning about Fluent NHibernate the other day.

    Where I hope NHibernate will help me:

    There is a lot of redundant data modeling and data mapping code that has to be created for enterprise applications and this really seems to be a great way to hit the ground running and rapidly develop a quick-hit enterprise or single instance web application. As I said in my previous post: We had to develop an app within 2 days (roughly 3-4 team-work-days) fueled by massive amounts of carbonated caffeine and fat content enriched edibles. This meant speed and extreme focus on customer use-case over creating architecture was important. Since it was low concurrent user volume there wasn’t need to worry about scaling up or out on this.

    My concerns & objectives going into NHibernate
    Learning the ORM and getting comfortable with it (this post is the second part of that for me)

    Dealing with Polymorphism in objects (Such as different types of bank accounts)

    Dealing with lots of records or large collections (Such as bank transaction history)

    Dealing with deep hierarchies or large object graphs (Such as bank customer records)

    Where it fits into horizontally scalable applications on a scale of millions of concurrent users

    Up till now

    I was able to get a modest FluentNHibernate example project running that created some referenced tables and filled them with data. I covered  utilizing the config file to do the connection string and how to exportSchema to do database creation.

     

    Today’s Post

                   I’m going to touch on some of the early items from the ‘playing with cats example’. Ok first step, let’s get some simple mapping on our cat with FN (ill use that now for Fluent NHibernate since I’m tired of typing it).

    public class CatMapping : ClassMap<Cat>

        {

            public CatMapping()

            {

                Id(c => c.Id)

                    .GeneratedBy

                    .UuidHex("N")

    /*  See Guid.ToString() for details

     *  http://msdn.microsoft.com/en-us/library/97af8hh4.aspx

     * */

                    .Length(32);

                   

                Map(c => c.Name).Length(16);

                Map(c => c.Sex).Nullable();

                Map(c => c.Weight).Nullable();

                Map(c => c.Height).Nullable();

                Version(c => c.Version);

                References(c => c.Father);

     

            }

        }

     

    As you can See I added a column for height, added a version number for long running transactions to utilize the optimistic offline lock functionality in NHibernate. Also I had to do a bit of searching to find out how to use the UuidHex method. Basically it creates a string column that is the output of Guid.ToString(string format).

     

    The cat entity (poco) looks like this:

        public class Cat

        {

            public virtual string Id { get; set; }

     

            public virtual string Name { get; set; }

     

            public virtual char Sex { get; set; }

     

            public virtual float Weight { get; set; }

     

            public virtual int Version { get; set; }

     

            public virtual float Height { get; set; }

     

            public virtual Cat Father { get; set; }

        }

     

    Generating and updating the Database Schema or DDL

    I have a few things to explain before I show the code… I used an IoC container for this. Specifically, I used NInject because I love it J If you check out the NHibernate documentation then that should give you enough information to understand what’s going on in this code:

     

    Working from the front to the back of the Database Creation webform/button:

    The button Handler

    Nothing fancy here… the button exports the schema to the database from the Configuration we’ve created… (Down further). The response.Write reference is an Action<string> that will write the generated DDL to the response for viewing. The true says: ‘yes, please export this in addition to outputting to screen go ahead and run it’

            protected void Button1_Click(object sender, EventArgs e)

            {

                new SchemaExport(NHibernateHelper.Configuration)

                    .Create(Response.Write, true);

            }

    The NHibernate Helper (relevant code)

      public sealed class NHibernateHelper

        {

            private const string NHibernateSessionKey = "nhibernate.context_session";

            private static ISessionFactory SessionFactory

            {

                get { return IoCRoot.Get<ISessionFactory>(); }

            }

            public static Configuration Configuration

            {

                get { return IoCRoot.Get<Configuration>(); }

            }

    /*ETC ETC…. same as nhibernate docs mostly except I changed the session key name. I didn’t like the word “Current” when referring to session. It’s the current context and the context has the session… so it would be a context session. Ironic coming from database people they’d have this WRONG ;) J J*/

    The IoCRoot global class

    This little guy will hold our NInject kernel and control which modules to load at construction/startup

        public static class IoCRoot

        {

            private static IKernel _kernel;

            static IoCRoot()

            {

                Startup();

            }

     

            public static void Startup()

            {

                _kernel = new StandardKernel();

                _kernel.Load<NHibernateModule>();

            }

     

            public static T Get<T>()

            {

                return _kernel.Get<T>();

            }

        }

     

    The NHibernate Module to get the IoC container ready

    Our ninject module controls what bindings we map to the IOC container. In this case a SessionFactory and a Configuration so we can pull those up whenever we want since they are application specific instances or global I’ve utilized my NInject version of the singleton pattern by using ToConstant() and providing an instance. Or so I hope J

        public class NHibernateModule : NinjectModule

        {

            private readonly ISessionFactory _sessionFactory;

            private readonly Configuration _configuration;

            public NHibernateModule()

            {

                _configuration = Fluently.Configure()

                    .Database(

                        MsSqlConfiguration

                        .MsSql2008

                        .ConnectionString(c =>

                            c.FromConnectionStringWithKey("connectionStringKey")

                            )

                        )

                    .Mappings(m =>

                        m.FluentMappings

                        .AddFromAssemblyOf<NHibernateModule>()

                        )

                    .BuildConfiguration();

                   

                _sessionFactory = _configuration.BuildSessionFactory();

            }

     

            public override void Load()

            {

                Bind<ISessionFactory>().ToConstant(_sessionFactory);

                Bind<Configuration>().ToConstant(_configuration);

            }

        }

     

     

    OK awesome. We have our database now… but let’s say we wanted to add or remove columns! Yikes…

    Updating Schema or DDL

    We simply use SchemaUpdate. Same thing as SchemaExport with Response.Write and the Boolean.

            protected void Button1_Click(object sender, EventArgs e)

            {

                new SchemaUpdate(NHibernateHelper.Configuration)

                    .Execute(Response.Write, true);

            }

    Making cats

    Just follow their guide: http://nhforge.org/doc/nh/en/index.html

    Querying Cats

    Same, follow their guide… nothing special there imo.

    Finding 1 Cat

    It seemed like their guide was out of date… here is what I came up with to select a cat by ID:

    oneCat = session.CreateQuery("from Cat as cat where cat.Id = :id")

                        .SetString("id",IdVariable)

                        .UniqueResult<Cat>();

     

    Finding all the cats

    Again… it was out of date or different than I had to write with FH

                List<Cat> cats = new List<Cat>();

                session.CreateQuery("from Cat").List(cats);

     

    In closing

    The arrangement of everything is quite good, FH makes things way easier than xml config files (in my opinion, especially with resharper and lambdas). I’m bothered by the nuisance of the ‘second query language’ that I have to learn to use nhibernate... but maybe Linq To NHibernate might help

     

     

     

    Source Code

     

     

     

     

     

     

     

     

     

    Full story

    Comments (0)

  • Using Fluent NHibernate to generate your database

     

     

    After my data access debacle at c4c I decided to sit down and give NHibernate a serious look again… so I can feel comfortable with it. It was still bothering me that I had to deal with xml configuration files (In addition to app.config/web.config). I really having to hunt down so many config files.

     

    Alas, the answer for that problem is Fluent NHibernate. I had heard the name mentioned before but I didn’t know what it was. Basically, there is no need to create mapping xml files, you just create mapping classes using lambda expressions in code. This gives you intellisense (yay for us lazy people)!

    http://fluentnhibernate.org/

     

    So to start learning Fluent NHibernate I was looking through the ‘first project’ example and remembered something Lee Brandt told me at C4C, “you can generate the sql ddl from within NHibernate to deploy your sql schema”. Fantastic! I wondered if I could do this with Fluent NHibernate too.

     

    The answer.

     

    Yes you can create your database from code using Fluent NHibernate… here is basically the snippet of code that had to change from the “First Project” example linked above:

     

           private static ISessionFactory CreateSessionFactory()

            {

                return Fluently.Configure()

                  .Database(MsSqlConfiguration.MsSql2008

                                .ConnectionString(c => c

                                .FromConnectionStringWithKey("connectionStringKey")))

                  .Mappings(m =>

                    m.FluentMappings.AddFromAssemblyOf<Program>())

                      .ExposeConfiguration(cfg => new SchemaExport(cfg)

                                                      .Create(false, true))

                  .BuildSessionFactory();

            }

     

     

    Now, you would only run this program once in this case because during the creation of the session factory we are generating the database (which would probably fail if you ran the program again).

     

    My thought is pulling it out into a method of it’s own to initiate only if the database doesn’t exist yet. Also, you could work in asking the user to enter in the connection information for the database server.

     

    Full story

    Comments (0)

  • Google bringing Gigabit Internet to Kansas City, KS

    http://www.msnbc.msn.com/id/42342322

    Read up... I personally haven't had a chance yet, but this is exciting news that will hopefully further break up the ISP monopolies and create better private sector competition and growth.

     

    Full story

    Comments (0)

  • C4C Recap and Lessons Learned

    As I was hacking around at Coders for Charities on my attempt at reproducing the Row Data Gateway Pattern from "Patterns of Enterprise Application Architecture" by Martin Fowler. By hacking around... I mean that I tried to be a good saint and start with using TDD, but after becoming completely bored with unit testing each added parameter to the SqlParameterCollection within a SqlCommand object I became completely disenchanted with the idea of doing that for the next 24 hours and not being any closer to a "Working Product".

     

    So... I wrote one unit test, testing the 'pattern' of what I was doing...then once end-to-end worked... I gave up the TDD.

    By all accounts this was the most cut and pasted code I've probably ever written...

    stuff like this:

    command.Parameters.AddWithValue("@parm1",Value1);

    ...Over and over for insert, update and deletes...

    Which... this was all because i felt that Entity Framework or NHibernate in a 'Time Crunch' situation would just be too much overhead...

    Sure... I was probably wrong :(

    And so anyhow, here I hacked away on my little slice of the pie... with no source control. Paul Meinhardt was jammin' out the SQL Database Table and SSIS import from Access, Cody Inman was rockin out the Sitefinity Skinning and several other sweet integrations (Paypal, Google Maps, Image Library), and Ross Fuhrman was writing an Excel export so the Business users could still do business the way they have for several years successfully.

     

    quick tangent: don't change how business is run and do not change how the data is stored (1 table, many columns) when you only have 2 days to do stuff.

    All of us split up doing our 'own thing', but integrating fairly decently, and finally coming down with a damned fine product in the end (I think) for what amounted to less than 25 team hours worth of work.

    Everything came out pretty damn nicely I think...

    The fruit of our labor: www.beltoncemetery.com

    So what were the key factors in our success?

    1. Onsite customer. Our customer stayed there most of both days with us and fielded questions. We probably under utilized them to be honest...
    2. Continuous Integration. We had the fully working site (but minimal) site deployed to discountasp.net by 10am in the morning on Saturday and we updated it religously and testing things (mostly manually) throughout both days. Always making sure it was working and we hadn't broken eachother. Then when we did... we talked and fixed it!
    3. Team communication/Collocation. We were tightly grouped together and looking at eachothers screens for the most part. It was amazingly wild.
    4. Energy Level and Fun. We tried to keep joking around and having fun. It's intense (especially when it's 80 degrees in our room because the AC was broken) when you're locked in together and working very hard... and breaking eachother's code and telling eachother how to do things :) :) (OMG u changed the data types! or 'Ugh all in 1 table?")

    So what would I do differently though?

    1. I need to learn an ORM so i can be successful at TDD in this type of situation.
    2. I need to get an IoC container setup next time so I can focus on just the interactions between presenters and the views. (Wasn't really a BLL in this app nor will there usually be in these types of apps)
    3. We need to get some sort of source control next time... people need to learn svn or git or somethin :)
    4. NOT use ftp remote site in VS2010
    5. bring a laptop for Ross
    6. Bring Vm we can all use with the same toolset
    7. vote an initial dev toolset before the night of! (pending the organization wanting something different ofc)

     

     

     

     

     

     

    Full story

    Comments (0)

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. Next page