Wednesday, August 24, 2011

Good enough

Saw a great talk today -- made by Eric Evans about DDD. Among other things he said that "Some things have to be good enough, while others have to really be good".

For me it basically means don't be running around trying to make design everywhere better, focus on the core (domain) instead.

Tuesday, July 19, 2011

In short

Well, it's been a while since I posted. In short, I've got a new woman, a new job, and version one of my opensource project has just been released. Check it out at http://poolkit.codeplex.com/

Sunday, March 13, 2011

Algorithms

While looking for a job I went on an interview which was focused on my ability to come up with solutions to algorithmic problems, and fast. The interviewers were sure it is the essence of the job (job title read: Senior C# Developer). I have always believed, my job is to create architectures that last and -- among other things -- I do like patterns that make algorithms unimportant, interchangeable. From my experience, it's rarely even required to optimize algorithms, and I never do this until a performance impediment arises (which is also rarely the case).

What's your take on this? Must a good software developer be fast and efficient when creating algorithms -- or is it more like a nice-to-have-but-not-necessary thing? (The answer may depend on the specifics of your project.)

Monday, January 17, 2011

Latest Brainbench Test

I've scored 4,51 on a .Net Framework 3.5 Fundamentals Brainbench test today. The transcript is here.

It says: "Scored higher than 99% of all previous test takers."

(Boasting does not really suit me. It can very well be the case that I was the second guy to take the test in the whole world. And that other guy fainted after the 3-rd question because his heater had burned out all oxygen in his room!)

Monday, December 27, 2010

State and CycledEnumerator

The GoF State pattern is not on top of my list of favorites (Decorator is), but I am using it from time to time. And as you probably are aware there is this question about the implementation of State: whoever will switch between states and when?

I thought that Iterator -- another GoF pattern -- might be a good example of something that encapsulates state switching logic in some cases, when the states are switched strictly in the order you know beforehand. I realize that not every State implementation is that simple, but if yours is, you might want to use the idea: just pass the IEnumerable of IState to the implementation of State, and use MoveNext() and Current {get;} on the Enumerator internally to switch states. If you are doing something like this, it might be a good idea to jump back to State #1 after you've reached State #Last. I've written a little helper class to do just that:

using System;
using System.Collections.Generic;

namespace Primitives
{
    public class CycledEnumerator<T> : IEnumerator<T>
        where T : class
    {
        private LinkedList<T> _chainedObjects;
        private LinkedListNode<T> _currentObject;

        public CycledEnumerator(IEnumerable<T> objectsToChain)
        {
            if (objectsToChain == null)
            {
                throw new ArgumentNullException("objectsToChain");
            }

            _chainedObjects = new LinkedList<T>(objectsToChain);

            if (_chainedObjects.Contains(null))
            {
                throw new ArgumentException("Nulls are not allowed.", "objectsToChain");
            }

            if (_chainedObjects.Count < 1)
            {
                throw new ArgumentException("Need at least one item in the set.", "objectsToChain");
            }

            this.MoveBeforeFirstElement();
        }

        private void MoveBeforeFirstElement()
        {
            _currentObject = null; // I don't like nulls at all, but I'm putting it here for the sake of consistency with Microsoft's implementations of Enumerator (which is a variant of GoF Iterator pattern).
        }

        public T Current
        {
            get
            {
                return _currentObject.Value;
            }
        }

        public void Dispose()
        {
        }

        object System.Collections.IEnumerator.Current
        {
            get
            {
                return _currentObject;
            }
        }

        public bool MoveNext()
        {
            if ((_currentObject == null) || (_currentObject.Next == null))
            {
                MoveToFirstElement();
            }
            else
            {
                _currentObject = _currentObject.Next;
            }

            return true;
        }

        private void MoveToFirstElement()
        {
            _currentObject = _chainedObjects.First;
        }

        public void Reset()
        {
            this.MoveBeforeFirstElement();
        }
    }
}

(That said, I don't like Iterator much (and all of its buddies, like the Enumerator): it exposes too much of its state to the client, and has too complex a contract. It's all like "if MoveNext() returns true, then Current contains the next element", or: "after initialization the Enumerator is positioned before the first element, and you should call MoveNext() to get anything from it".)

Gang Of Four Patterns

Some days I find myself really believing that Gang Of Four patterns describe about 90% of all domain-model-related software design tasks out there. On our last design meeting I only had to name the applicable patterns, and that about did it: "Huh, this can be done with a Visitor", or "Sounds like an ordinary Composite to me"... That is not to say I'm good, but rather to reiterate what this guy told me once: "Everything has already been written".

("Design Patterns: Elements of Reusable Object-Oriented Software" was one of the first books I've read on the subject, years ago, and it's a really good read.)

Monday, August 23, 2010

Databases vs. everchanging model

This sprint I've been struggling hard to postpone the creation of a database to back up WCF service operations 'till next sprint. Last sprint I've insisted on keeping the store of service objects in memory - so the service loses all data upon restart. This was enough to make an iteration (and I think it was a good decision) but a lot of people on the team pushed back.

The reason I don't want a database from day 1 is our domain model is undergoing such changes that it would have taken us an entire sprint redesigning the database for every change, if we had decided to go down that road. We've spent that time on useful things instead, I hope.

Last week we, again, came to a point where a decision was needed on whether to create the database or not. And once again I pushed back, so we've chosen to save all data into a single file (having more than one would require extra work for reconstructing object references) using plain old data contracts. A question came up though: how do you save all those different collections of domain model elements preserving object references between those collections? The answer to that was dumping all objects into a List<object>, creating a DataContractSerializer around it (with exactly that type - List<object>), feeding to the serializer a list of known types made of all types of contracts (note that it's no longer domain model elements) that are used to store the state of the service, telling the serializer to preserve object references. Of course, all of this would still be hard to do (because of reference fixups), if we had not decided to use data contracts everywhere for the state of the service - as opposed to domain model objects we had in sprint 1.

Note that this is a temporary solution, we will migrate to a database at some point. That said, I suppose modifying data contracts is slightly easier than modifying the database -- I may be exaggerating the complexity of making changes to the databases since I haven't seen any database refactoring tools, and there must be some.

(When putting the reconstructed object graph' elements back to their collections we've iterated thru deserialized elements and added them to appropriate collections depending on the type of element).

Could post the code proving the concept works, if anyone is interested.