Blog

Filter posts by Category Or Tag of the Blog section!

Vianna

Monday, 10 December 2018

Vianna is the new generation of LMS system which has been started developing since January 2017 in Vesta incorporation by starting my cooperation. The previous LMS product of Vesta has played the main role on e-learning in lots of universities and organizations during the last decade and now Vianna is being developed by the majority of experiences. It’s a sort of large-scale and enterprise application with the target of extending to be more than just a Learning Management System. This project belongs to Vesta company and it's not open source, so I'm just allowed to talk about the overall architecture and a few pictures from the production environment with their agreement and permission. Vianna has been designed to be distributed and extendable.

If you are familiar with LMS systems, Vianna supports for Announcement, Exam, Forum, Messaging, Learning Path, Notification, Practice, Scorm, Virtual Class, Multiple Branches, Multilingual, etc. Now we are in the first version of the product. I'm just taking a glance at the architecture of the project as talking about the business deserves writing a book about. As an overall look to the solution, you can see in the picture below, the main application and the distributed applications are living in one solution:

 

 

Giving a name for the architecture of such an application is so hard. In overall, it's Model Driven Architecture and the business layer is separate from the model. I start the describing by Framework layer. The framework consists of all the infrastructural configurations of the system such as Caching, Exceptions, IOC, Membership, Messaging, Security, Patterns base classes, and the LMS infrastructural requirements like Scorm Engine and Virtual class. The business class library contains all the business rules of the system and the implementation of a simple business class is like the below piece of code:

 

public class ExamBusiness : BaseBusiness<Model.Exam.Exam>
    {
        private readonly Model.Exam.Exam _exam;

        public ExamBusiness(Model.Exam.Exam exam) : base(exam)
        {
            _exam = exam;
        }
        protected override void Validate()
        {
            if (_exam.StartDate != null && _exam.StartDate > DateTime.Now)
            {
                AddBrokenRule(ExamBusinessRule.UpcomingExam);
            }

            if (_exam.EndDate != null && _exam.EndDate < DateTime.Now)
            {
                AddBrokenRule(ExamBusinessRule.ExpireExam);
            }
        }

        public int GetExamDuration()
        {
            if (_exam.EndDate != null && _exam.EndDate.Value.Date == DateTime.Now.Date)
            {
                if (_exam.EndDate.Value.Minute > DateTime.Now.Minute)
                {
                    if (_exam.EndDate.Value.Minute - DateTime.Now.Minute < _exam.Duration)
                    {
                        _exam.Duration = Convert.ToInt32((_exam.EndDate.Value.Minute - DateTime.Now.Minute));
                    }
                }
            }

            return _exam.Duration.Value;
        }


        public List<BusinessRule> validateExamDate(PresentedLesson presentedLesson)
        {
            List<BusinessRule> _brokenRules = new List<BusinessRule>();
            if (_exam.StartDate==null)
            {
                _exam.StartDate = presentedLesson.BeginDate;
            }
            if (_exam.StartDate < presentedLesson.BeginDate)
            {
                _brokenRules.Add(ExamBusinessRule.ValidateExamDate);
            }

            return _brokenRules;

        }
    }


  public class ExamBusinessRule
    {
        public static readonly BusinessRule UpcomingExam = new BusinessRule("Exams", "A message");
        public static readonly BusinessRule ExpireExam = new BusinessRule("Exams", "A message");
        public static readonly BusinessRule ValidateExamDate = new BusinessRule("Exams","A message");
    }

 

 And the implementation of the base Business class:

 

 public abstract class BaseBusiness<TEntity> where TEntity : class
    {
        private readonly List<BusinessRule> _brokenRules = new List<BusinessRule>();
        private readonly TEntity _entity;

        protected BaseBusiness(TEntity entity)
        {
            _entity = entity;
        }

        public TEntity Entity { get; set; }

        protected abstract void Validate();

        public IEnumerable<BusinessRule> GetBrokenRules()
        {
            _brokenRules.Clear();
            Validate();
            return _brokenRules;
        }

        protected void AddBrokenRule(BusinessRule businessRule)
        {
            _brokenRules.Add(businessRule);
        }
    }


 

The business rule classes are being used in service layer which interacts with Data(Persisting/Retrieving data to/from database). The Web application projects of the system are coupled to the service layer.  If you look at the dependency graph of the solution, you will understand the whole schema:

 

 

And the production block we are tackling most of the time with:

 

 

As you can see in the picture above, the framework plays an important role in the system. The distributed block which contains logging, Identity, queue, and CDN are connected to the Vianna by calling services like API and WCF. In order to show you the production environment, the picture below shows the dashboard of the admin panel:

 

 

And the learning path section:

 

 

To be frank, I'm not allowed to share more than above! Vianna is so big project and we have developed lots of business values about LMS in this project. The project is under development and we have done only the first phase of the project out of four. If you need to know more about Vianna you call refer to http://vestasoft.ir/ and send email to info@vestasoftware.ir

 

Category: Software

comments powered by Disqus