Chapter 5: Conclusion And Future Work
5.2 Future Work
This thesis has proposed Five Class Normal Forms in the form of rules to be applied to a programming class during software development. These rules can be understood by a software programmer and the programmer could manually follow these rules to make sure a programming class is normalized. However, these rules could potentially be translated into programmatic rules and could be fed into a software system. This software system could then be used to validate a software solution to see if any entity
programming classes within the software solution violate any of the Class Normalization rules discussed in this thesis. This type of a software program, once developed, could be used as part of the software build and deployment process of an enterprise. That way, an enterprise can make sure that their database is completely normalized.
A sample prototype program on how this can potentially be implemented is appended to Appendix A of this thesis. The program validates the most common cases of violations of the First Class Normal Form (1CNF) and outputs the error/warning messages found. The program points out exactly which programming entity class has errors and also gives
suggestions on how to fix the errors. This program does not modify the entity classes automatically. Modifying a programming class automatically can cause various issues for a programmer because the classes that are newly modified/created by the automated program can cause new compilation errors due to how they may fit into the rest of the solution. That is why several plugins and helper tools validate a program and let the programmer know about any errors or warnings so that the programmer could surgically fix the errors. This works much like how compilers for several programming languages work. Compilers will cite the errors in syntax, but the repair needs to be done by the programmer.
The example validation program provided in the Appendix serves as an example of how an automated system could be developed to validate all the five Class Normal Forms (1CNF – 5CNF) for a given set of entity programming classes.
The inputs and outputs of the validation program to validate the First Class Normal Form are provided below:
Input entity programming class:
namespace ClassNormalization.Sample {
public class Contact {
public string Name1 { get; set; } public string Name2 { get; set; } public string Name3 { get; set; }
public string Address { get; set; } }
}
Figure 7: Console Output
The sample program provided concludes its diagnostics at validating the First Class Normal form because validating additional Class Normal Forms (2CNF – 5CNF) is challenging and is beyond the scope of the thesis.
For example, here is a sample class that violates 2CNF:
public class Order {
public int CustomerID { get; set; } public int StoreID { get; set; }
public int StoreLocation { get; set; } }
From the above program, it can be seen that 2CNF is violated because the StoreLocation property belongs in the Store entity class and does not belong in the Order entity. Any software programmer can easily make that determination by looking at the class and split the Order class as seen below:
public class Order {
public int CustomerID { get; set; } public Store Store { get; set; } }
public class Store {
public int StoreID { get; set; }
public string StoreLocation { get; set; } }
However, a program cannot automatically detect a violation of 2CNF unless the program has additional information that may include the following:
Complete knowledge of the domain of the solution.
Metadata on the semantic meaning of different entity classes in the solution. The exact usage data of the classes/attributes in the domain and the entire
software solution.
Additional information to detect 2CNF and above might be needed based on the
implementation of the solution. It can be done. However, it will have to be its own thesis with a thorough research on all possible solutions and implementation details.
Although it may seem feasible, building a software system sufficiently sophisticated to understand the Class Normal Form rules (2CNF – 5CNF), their semantic meaning, and validating an entity class would be a major undertaking indeed. Complexities associated
with diagnosing and repairing such software (understanding the application domain, related semantics and more) may be some of the reasons why such software is not currently available.
REFERENCES
Print Publications: [Ambler97]
Ambler S., Building Object Applications That Work: Your Step-By-Step Handbook for Developing Robust Systems with Object Technology, New York: Cambridge University, 1997.
[Ambler03]
Ambler, S., Agile Database Techniques: Effective Strategies for the Agile Software Developer, Wiley, 2003.
[Booch94]
Booch, G., Object-Oriented Analysis and Design with Applications, Redwood City, Calif: Benjamin/Cummings Pub. Co, 1994.
[Bura12]
Bura, D. and R. K. Singh, "Implementing Constraints in Entity-Relationship Models for Enhancing Normalization," IUP Journal of Information Technology 8, 2 (June 2012), pp 46-57.
[Coad92]
Coad, P., "Object-Oriented Patterns," Communications of the ACM 35, 9 (September 1992), pp 152-159.
[Codd70]
Codd, E. F., “A relational model for large shared data banks,” Communications of the ACM 13, 6, (June 1970), pp 377-387
[Date12]
Date, C. J., Database Design and Relational Theory: Normal Forms and All That Jazz, O'Reilly Media, 2012.
[El-Sofany09]
El-Sofany, H. and S. Abou El-Seoud, "Schema Design and Normalization Algorithm for XML Databases Model,” International Journal of Emerging Technologies in Learning 4, 2 (May 2009), pp 11-21.
[Fowler92]
Fowler J. and M. West, “Developing High Quality Data Models,” The European Process Industries STEP Technical Liaison Executive (EPISTLE), 1992.
[Gamma95]
Gamma, E., Design Patterns: Elements of Reusable Object-Oriented Software, Reading, Mass: Addison-Wesley, 1995.
[Gorman90]
Gorman, K. and J. Choobineh, "The Object-Oriented Entity-Relationship Model (OOERM)," Journal of Management Information Systems 7, 3 (October 1990), pp 41-65
[Kent83]
Kent, W., "A simple guide to five normal forms in relational database theory," Communications of the ACM 26, 2 (February 1983), pp 120-125.
[Lee95]
Lee, B. S., "Normalization in OODB design," SIGMOD Record 24, 3 (September 1995), pp 23-27.
[Lerman12]
Lerman, J. and R. Miller, Programming Entity Framework: Code First, O'Reilly Media, 2012.
[Liles12]
Liles, D. and T. Rayburn, Entity Framework 4.1: Expert's Cookbook, Birmingham, UK: Packt Publishing, 2012.
[Martin09]
Martin, R., Clean Code: A Handbook of Agile Software Craftsmanship, Pearson Education, Inc, 2009.
[Merunka13]
Merunka, V. and J. Tůma, “Normalization Rules of the Object-Oriented Data Model,” In Proceedings of the International Workshop on Enterprises & Organizational Modeling and Simulation, 2009
[Nien-Lin09]
Nien-Lin, H., K Jong-Yih and L. Ching-Chiuan, "Object-Oriented Design: A Goal Driven And Pattern-Based Approach," Software & Systems Modeling 8, 1 (February 2009), pp 67-84.
[Stephens09]
[Torres17]
Torres A, Galante R, Pimenta M, Martins A., “Twenty years of object-relational mapping: A survey on patterns, solutions, and their implications on application design,” Information and Software Technology, 82 (February, 2017), pp 1-18.
APPENDIX A
First Class Normal Form Validator Prototype
using ClassNormalizationRules; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ClassNormalFormValidator {
public class Program
{
public static void Main(string[] args) {
Console.WriteLine("Enter the directory that contains your entity classes:");
string dirPath = Console.ReadLine(); ClassNormalFormsValidator validator = new
ClassNormalFormsValidator(); try
{
List<string> loadErrors = validator.Load(dirPath); if(loadErrors.Count > 0)
{
Console.WriteLine("Error encountered during
compilation of the source code:");
foreach (string error in loadErrors) { Console.WriteLine(error); } } else {
List<ValidationResult> validationResults = validator.GetValidationResults();
if (validationResults.Count > 0) {
Console.WriteLine("\r\nPlease fix the following
foreach (ValidationResult result in
validationResults)
{
Console.WriteLine("\r\n");
Console.WriteLine(result.Level ==
ValidationLevel.Waning ? "Warning" : "Error" + ": " + result.Violation);
Console.WriteLine("How to fix the issue: "
+ result.HowToFix); Console.WriteLine("--- ---"); } End(); } else {
Console.WriteLine("No errors found!"); End(); } } } catch (Exception e) { Console.WriteLine(e.Message); End(); } }
private static void End() {
Console.WriteLine("\r\n");
Console.WriteLine("Press Enter to quit"); Console.ReadLine(); } } } using Microsoft.CSharp; using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ClassNormalizationRules {
public class ClassNormalFormsValidator
{
{
List<string> sources = new List<string>(); List<string> errors = new List<string>();
foreach (string file in Directory.GetFiles(dirPath,
"*.cs")) {
sources.Add(File.ReadAllText(file)); }
CompilerParameters parameters = new CompilerParameters(); parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
parameters.ReferencedAssemblies.Add("mscorlib.dll"); parameters.ReferencedAssemblies.Add("System.dll"); var provider = new CSharpCodeProvider();
var results =
provider.CompileAssemblyFromSource(parameters, sources.ToArray()); if (results.Errors.HasErrors)
{
foreach(CompilerError error in results.Errors) {
errors.Add(string.Format("Compilation Error at: {0}
with Text: {1}", error.Line, error.ErrorText));
}
return errors; }
var assembly = results.CompiledAssembly; var assemblyTypes = assembly.GetTypes(); foreach (Type type in assemblyTypes) {
_types.Add(type); }
return errors; }
public List<ValidationResult> GetValidationResults() {
var validators = GetValidators();
var results = new List<ValidationResult>(); if(_types.Count == 0)
{
return results; }
foreach (IClassNormalFormValidator validator in validators) { results.AddRange(validator.GetValidationResults(type)); } } return results; }
private List<IClassNormalFormValidator> GetValidators() {
var validators = new List<IClassNormalFormValidator>(); validators.Add(new FirstClassNormalFormValidator()); return validators; } } } using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace ClassNormalizationRules {
public class FirstClassNormalFormValidator :
IClassNormalFormValidator
{
private Type _type;
private List<ValidationResult> _results;
public List<ValidationResult> GetValidationResults(Type type) {
_type = type;
_results = new List<ValidationResult>(); ValidateIdentifier();
ValidateSingleValue(); ValidateRepeatingGroups(); return _results;
}
private void ValidateIdentifier() {
PropertyInfo[] properties = _type.GetProperties(); bool idFound = false;
// try to find a property with {ClassName}ID, ignpring case
if(string.Compare(property.Name, _type.Name + "id",
true) == 0) { idFound = true; } } if (!idFound) {
_results.Add(new ValidationResult {
Violation = "(" + _type.Name + ".cs) Violation of
1CNF: No two object can have identical values.",
HowToFix =
@"Please add an identifier property to your class in the format {ClassName}ID and make
sure a unique value is always assigned to this property before saving
an instance of this class to the database.",
Level = ValidationLevel.Error });
} }
private void ValidateSingleValue() {
PropertyInfo[] properties = _type.GetProperties(); foreach (PropertyInfo property in properties) { if (property.PropertyType.IsArray) { Type elementType = property.PropertyType.GetElementType(); if(elementType.IsPrimitive || elementType.Name.ToLower() == "string") {
_results.Add(new ValidationResult
{
Violation =
"(" + _type.Name + @".cs) Violation of 1CNF: Each property must contain
a single value unless
it is a collection of a type that is part of the entity model.",
HowToFix = string.Format(
@"The property type of the property '{0}' is an array of either a primitive
type or a string. To fix it, please create a new class that for the property '{0}'
to store the values for '{0}' and link it back to the class '{1}'",
property.Name, _type.Name),
Level = ValidationLevel.Error });
} }
private void ValidateRepeatingGroups() {
PropertyInfo[] properties = _type.GetProperties(); List<string> numberedProperties = new List<string>(); string numberedProperty = null;
foreach (PropertyInfo property in properties) { if (property.Name.EndsWith("1")) { numberedProperty = property.Name.Substring(0, property.Name.Length - 1); break; } } if(numberedProperty != null) {
foreach (PropertyInfo property in properties) {
string prop = property.Name.Substring(0, property.Name.Length - 1); if (prop == numberedProperty) { numberedProperties.Add(property.Name); } } } if (numberedProperties.Count > 1) {
string numberedPropertiesString = string.Join(", ", numberedProperties.ToArray());
_results.Add(new ValidationResult
{
Violation = "(" + _type.Name + ".cs) Violation of
1CNF: Properties cannot contain repeating groups.",
HowToFix = string.Format(
@"The properties '{0}' are considered repeating groups.
Please give each of those properties some contextual names.",
numberedPropertiesString),
Level = ValidationLevel.Error }); } } } } using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespace ClassNormalizationRules {
interface IClassNormalFormValidator
{
/// <summary>
/// Validates all rules related to this class normal form
/// </summary>
/// <returns>A list of error/</returns>
List<ValidationResult> GetValidationResults(Type type); } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ClassNormalizationRules {
public enum ValidationLevel
{ Error, Waning } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ClassNormalizationRules {
public class ValidationResult
{
public string Violation { get; set; } public string HowToFix { get; set; }
public ValidationLevel Level { get; set; } }
VITA
Daniel Sudhindaran has Bachelor of Science degree from the University of North Florida in Computer Science, 2007 and expects to receive a Master of Science in Computer and Information Sciences from the University of North Florida, April 2017. Dr. Robert Roggio of the University of North Florida is serving as Daniel’s thesis advisor. Daniel is currently employed as a Product Architect at Beeline and has been with the company for ten years.
Daniel has an on-going interest in innovation and startups. Daniel co-founded two companies – TradeSumo and Zwytch. TradeSumo is an online bartering marketplace where people can swap their unused stuff for free. Zwytch is an online car buying
platform that helps users chat real-time with multiple dealers around them and negotiate a complete car deal before going to the dealership. Daniel has extensive programming experience in C#, .NET, JavaScript, SQL, HTML and CSS. Daniel’s academic work has included the use of Java and C programming languages as well.