Introduction One more theory book on software design and this book explains the simplicity of code. …
No application is in island. Every application needs to interact with other applications located in…
Introduction It is very interesting to read a hard core computing book from authors those…
Hope you know what is DSL (domain specific language). It is a programming language aimed for a particular domain with the users in that domain in mind. DSL is differed from general purpose programming languages (C#, Java, Ruby, Python) that DSL is limited to a particular problem domain whereas general purpose languages are made for addressing any kind of problems in the world. For example, your NANT build scripts and Unix shell scripts are some of the examples DSLs. Yes, DSL is not new. Note that the area for DSL can be finnancial, maths, science, health-care, space control, etc.
A DSL can be created either on top of existing programming languages like C#, Ruby, etc, or created from scratch by using parser-generator tools like ANTLR, Irony. Martin Fowler coined the name "Internal DSL" for first one and for the second one he called as "External DSL". Internal DSL are designed by using the syntax and the level extensibility provided in the hosting language. For internal DSL, Ruby is the first class citizen for this due to its by birth nature and other features like metaprogramming. By the way, C# (my primary language) also has the capability to build a DSL.
In this article, I create a DSL for examination question paper in C#. This DSL enables to create an examination with multi-choice questions. Also, it provides API to validate the answers. Let us start with plain C# classes without any DSL flavor. During the journey, I'll top-up the DSL flavors until We reach a point where you should feel it is the language for this particular problem domain.
The below diagram depicts the domain model for this domain.
public class Exam { public string Title { get; private set; } public Level Level { get; private set; } public ListQuestions { get; private set; } public Exam(string title, Level level) { Title = title; Level = level; Question.QNo = 1; Questions = new List (); } public void AddQuestion(Question question) { if (!Questions.Contains(question)) Questions.Add(question); } public void VerifyAnswers(ref Dictionary answers) { foreach (KeyValuePair answer in answers) { Question question = Questions.Find(q => q.Number == answer.Key); if (question.Answer.SequenceEqual(answer.Value.Answer)) answer.Value.IsCorrect = true; else { answer.Value.IsCorrect = false; answer.Value.CorrectAnswer = question.Answer; } } } }
public class Question : IEquatable{ internal static ushort QNo { get; set; } public ushort Number { get; private set; } public string Description { get; private set; } public Dictionary Options { get; private set; } public List Answer { get; private set; } public Question(string description) { Number = QNo++; Description = description; Options = new Dictionary (4); } public void AddOption(string choice, string descripton) { if (!Options.ContainsKey(choice)) Options.Add(choice, descripton); } public void AddAnswers(string[] choices) { Answer = choices.Distinct().ToList(); } public override bool Equals(object obj) { if (ReferenceEquals(this, obj)) return true; if (obj == null || !(obj is Question)) return false; Question other = obj as Question; return Number == other.Number && Description.Equals(other.Description) && Options.Equals(other.Options) && Answer.Equals(other.Answer); } public override int GetHashCode() { return Number.GetHashCode() ^ 786 ^ Description.GetHashCode() ^ Options.GetHashCode() ^ Answer.GetHashCode(); } #region IEquatable Members public bool Equals(Question other) { if (ReferenceEquals(this, other)) return true; if (other == null) return false; return Number == other.Number && Description.Equals(other.Description) && Options.Equals(other.Options) && Answer.Equals(other.Answer); } #endregion }
Souce code for AnswerSheet and Level are not required, since the class diagram represents them well. If you think, the above code is fine to create a exam paper by a question paper preparer, you will definitely reconsider after you see the below code.
var dotnetExam = new Exam(".NET Fundamentals", Level.Beginner); Question question = new Question("Expansion of CLR"); question.AddOption("A", "Common Language Runtime"); question.AddOption("B", "Common LINQ Runtime"); question.AddOption("C", "C# Language Runtime"); question.AddOption("D", "C Language Runtime"); question.AddAnswers(new string[] { "A" }); dotnetExam.AddQuestion(question);
The above lines are very bulky, object name and methods are messed up with C# syntax for just adding one question. In practical, a question paper contain at least 25 question. Just consider the question paper preparer who is going to use this API. He need to play lot around with (, ), Shift key, {, } characters without semantically understanding of these.
Comments |
|
|
< Prev |
---|
© 2011 Udooz.net All Rights Reserved.