Continuing with our full app creation series, Lunchage.
Part of my enthusiasm in creating the Lunchage application is the prospect of new beginnings. Every new project requires significant amounts of thought into my favorite activity, modeling out a domain. I believe the single most important aspect of a software engineer’s tool belt is the ability to translate real-world requirements into a set of classes that:
So, with these lofty goals in mind, we’re going to be keeping a very strict sense of Object Oriented Design in mind when developing and writing out the classes in our main domain model. I’ve dealt with plenty of DTO/Domain model hybrids in the past with feature envy and am looking to this project to display exactly how easy life can be when we allow our domain to properly encapsulate logic instead of merely providing an interface into our database as is the case with many other systems.
In you’re interested at all in following along with the code base, feel free to download it from github.
Instead of listing every property and field on all our our domain models, I’ll simply say that if a property is necessary for an object to exist, we make sure that it is passed into a constructor to force on instantiation. In addition, we’re going to try and force all List types to be only mutable by the parent. This means no public getter on lists, we’ll supply a public getter in the form of IEnumerable so no other classes can modify the list.
Since our requirements dictate that users need to be able to log in and create an account with Lunchage we’re going to create a, wait for it, Account class. I want to try an avoid having a needless amount of properties on the class so naturally my first instinct is to simply add first name, last name and email as the only identifiers of a user that I need. Further down the line we’ll add avatar support but, in keeping in line with light requirements, that stuff is fluff so it’s out for now. Email is the one property an account needs to be created, so we’ll force that dependency in the constructor and only have a getter backing a private property to allow field access. In the future if we (read: when) want to allow changing the email we can add a setter with some null checking logic, but for the time being we’re creating a contract with a property that always needs to be there, so let’s make sure that it is.

Our Account class is also going to need a list of properties to track when they choose a place to have lunch. I’ll then create a LunchSelection class, which is largely immutable, to store the relationship between a Restaurant selected, an Account and the time the lunch is supposed to take place. After the lunch we’ll allow the user to submit series of reviews on the service, food quality etc….

The Restaurant class is just as simple as our Account class. We need an Address to store it’s location for geo-targeting, a name, a list of descriptive Tag objects and a list of LunchSelection objects that were created in conjunction with the Restaurant.

You’ll notice we have a list of Reviews attached to the LunchSelection, this may seem a little silly at the moment, I’ll explain this decision after describing the Review class properly. A Review is made up of a user’s Vote (Great, Ok, Bad), the Question they answered (How was the service? How did the food taste? etc…) and the LunchSelection for bi-directional reference. All properties on this class are immutable, largely because once you review something, you really can’t take it back. The premise is that we want multiple mini-reviews for a LunchSelection that describe fully the experience they had. Restaurants can be crappy some days because of service and excellent simply because of the atmosphere. We want to capture the flowing nature of this information.

Voting in our Lunchage system is designed to be hyper-simple to the point of almost Yes-No question answer pairs. We have to assume most people don’t want to spend the time on diatribes about the quality of their lunch, we need to capture their experience though in order to properly recommend other restaurants. So we can ask brief questions like “How was the service?” with Netflix style emails to hopefully garner a response. Vote is then only going to have a VoteValue, which is an enum for Great, Ok or Bad, comments should the user want to provide them and the LunchSelection it is tied to.

The last major class in our system (as per our initial requirements) is going to be the Tag. A Tag is a name describing the type of food a restaurant serves. Tags can range from Chinese or Italian to simply Spicy. Our goal is to create a really dumb selection process that invites the user to blindly click buttons of words they like. Next thing you know they’re eating lunch at a restaurant they love and have never eaten at and thanking us for making suggestions.

From here the real work on the application begins. We need to get rolling on our storage mechanism implementation and, from there, whatever testing framework we’re going to use to make sure this code-base doesn’t become a mess. We may have to slightly alter our model once we choose ORM solutions, but we’ll get to that next time.
Again, if you want to check out the codebase, feel free to download it here.
Some text here...