+ All Categories
Home > Documents > PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn...

PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn...

Date post: 01-Jul-2020
Category:
Upload: others
View: 0 times
Download: 0 times
Share this document with a friend
13
CODE AUDIT PHONE (877) 644.6373 FAX (952) 948.1611 EMAIL [email protected] WEB http://nerdery.com MCAPS MN Counties Computer Cooperative Project #20138T Prepared By Paul Trandem Lead Developer, PSE Andrew Morger Intake Developer, PSE Mike Curry Senior Software Project Manager Client Contact Lisa Meredith MnCCC Executive Director [email protected] 6519176996 Nerdery Contact Mike Curry Senior Software Project Manager [email protected] 9525826587 PAGE 1 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions
Transcript
Page 1: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

CODE AUDIT PHONE (877) 644.6373 FAX (952) 948.1611 EMAIL [email protected] WEB http://nerdery.com

MCAPS

MN Counties Computer Cooperative Project #20138T

Prepared By

Paul Trandem ­ Lead Developer, PSE Andrew Morger ­ Intake Developer, PSE Mike Curry ­ Senior Software Project Manager

Client Contact

Lisa Meredith MnCCC Executive Director [email protected] 651­917­6996

Nerdery Contact

Mike Curry Senior Software Project Manager [email protected] 952­582­6587

PAGE 1 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 2: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

DOCUMENT OVERVIEW The purpose of this document is record the findings of the code audit pertaining to code quality, security, and maintainability. Primary benefits are maintaining a log of project risks inherent in the code base, as well as factors that would affect maintainability and future enhancement effort. Intended audience members include:

Project stakeholders Project management Business analysts Estimators Developers Quality assurance team members

CODE OVERVIEW The Code Intake and Audit included reviewing provided application code in an effort to judge the following basic categories of code quality: proper usage of the programming language, proper usage of the development framework, consistent code formatting, code commenting, reusability, maintainability, and proper separation of concerns. Additional attention was payed to specific performance concerns as well as system architectures and tertiary concerns.

TECHNOLOGY OVERVIEW

OBSERVATION / TOPIC COMMENT

Production environment The production environments vary, but are expected to be desktop workstations and a single office workstation with SQL 2008 R2

Programming Language C#, XAML

Frameworks Usage .Net (DotNet) Framework Version 4 Windows Presentation Foundation (WPF) Aspose Words DevExpress Libraries Syncfusion Libraries Hibernating Rhinos Enterprise Library Profiler Microsoft Prism Library Microsoft Enterprise Library Microsoft Unity

PAGE 2 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 3: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

MAINTAINABILITY

FRAMEWORK USAGE The following major frameworks are being used in the application.

Windows Presentation Foundation (WPF) Microsoft’s WPF is the overarching application framework for UI and windows application development. This framework selection is the logical choice for this an application.

Aspose Words Aspose Words is a third­party library used for interacting and creating Microsoft Word documents.

DevExpress Libraries DevExpress is a third­party library used to provide specialized UI controls and features that don’t come as part of WPF natively.

Syncfusion Libraries Like DevExpress, Syncfusion is a third­party library used to provide specialized UI controls and features that do not come as part of the WPF framework. There is overlap in the types of controls and features offered by the two libraries, however each has their strengths and unique controls that the other doesn’t offer. It is not common that these two libraries would be used together, however it is also not likely a problem either.

Hibernating Rhinos Entity Framework Profiler Hibernating Rhinos Entity Framework Profiler is a library that is used to troubleshoot and gain insight into the performance of the application’s usage of Microsoft’s Entity Framework library.

Microsoft Prism Library This is Microsoft’s original MVVM (Model, View, View Model) Framework. Modern WPF applications are built using MVVM pattern, but it is not as common anymore to see Prism used. MVVM Light or Caliburn Micro are the two big MVVM Frameworks used by most application developers. Prism implementations are overly prescriptive and inflexible compared to the more modern MVVM frameworks. It should be noted that Prism is still supported by Microsoft. The version in the application is 2.0; the latest version from Microsoft is version 5.0.

Microsoft Unity Unity is an older Dependency Injection Framework developed by Microsoft. Dependency Injection is a means to decouple parts of systems from each other and is a very good thing to have in an application.

PAGE 3 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 4: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

Over the years Unity has been replaced by more modern libraries like Ninject or AutoFac for dependency injection and Microsoft’s Managed Extensibility Framework (MEF) for plugin support. Unity is still an active project within Microsoft, however the version used in the application (2.0.x) has been retired by Microsoft. Unity has similar problems to Prism, where it is overly­prescriptive and inflexible. The current application developer cited Unity as the source of memory leaks. We suspect the issue may lie in fact that the Unity framework isn’t releasing Views and View Models for garbage collection. Caliburn Micro, one of the more modern libraries, has a concept called View Caching that allows for reuse of views that helps prevent memory leaks. Of note: Throughout the code the Dependency Injection framework is used in inconsistent manners. In some cases Construction Injection is used and in others they use a Service Locator pattern. This inconsistency it makes it very hard for developers to discern how the code is tied together. It also makes it very difficult to ever go back and attempt to unit test (see Unit Tests below).

Microsoft Enterprise Library Enterprise Library is a base requirement for both Prism and Unity. It also comes with other features, such as logging solutions that are often needed for applications. However, like Prism and Unity, Enterprise Library is aging and often individual features of Enterprise Library are replaced by specialized libraries that do just one thing, and do it better. For instance, Enterprise Library Logging might be replaced with Log4Net, NLog, or even an enterprise logging cloud service such as Raygun. Ideally, Unity, Prism and Microsoft Enterprise Library would not be used in new development, in favor of more modern libraries. Unfortunately, due to the way the application is designed around the Prism and Unity frameworks, the effort to swap them with this codebase out could be high.

SOLUTION ARCHITECTURE

Solution Organization

A .Net “Solution” contains and organizes one or more “Projects” that contribute to a single output. In this case, that output is the application executable file. A .Net Project contains and organizes code files that contribute to a single assembly (DLL file). The application solution is organized into projects (DLL assemblies) with dependencies as depicted below.

PAGE 4 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 5: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

The overarching organization of the projects into solution folders (Modules, Common) is good. However, the sheer number of project­specific assemblies (DLLs) appears excessive, at a count of approximately 30 for a single application. There are valid reasons separating code into assemblies, such as for re­use between different applications, plug­in architectures, and others.

PAGE 5 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 6: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

These separations come with several costs though, and one is performance. On the surface it appears that, for this application, the majority of the assemblies could be combined into fewer, larger assemblies without losing any functionality. Significantly reducing the number of assemblies will likely result in 1) some performance increase, especially during application startup and, 2) faster compile times for the application developers when developing on the codebase. It may also reduce the memory footprint of the application to some degree.

Project Organization The organization of projects within the solutions are somewhat inconsistent. Ideally, a high percentage of code files would organized into folders and very few would be in the root of the project. This keeps projects tidy and efficient for developers. The five “Common” projects all have a large number of files in the project root that can be organized further. On the other hand, the Modules projects and the MCAPS Desktop project have relatively few files in the project root and appear well organized.

Separation of Concerns While the code itself is broken into many projects (which looks very nice on the surface), many of these projects have created direct inter­dependencies within each other and don’t follow best practices of centralizing logic and functionality. This can make it very difficult for developers to make changes because they don’t know what the changes will break.

File & Folder Organization During the review, we had issues getting the codebase up and running due to file and folder organization:

1) Folder organization was slightly confusing, containing multiple projects and solutions with different directory hierarchy approaches.

2) Not all necessary third­party DLLs were present in the Library folder making it impossible to build the solution “out of the box”; we eventually located most of the necessary DLLs in the bin folder of the MCAPS Desktop project. Bin folders are volatile directories that are wiped during a Clean & Rebuild operation, thus they are not a good place to store DLLs for long­term use.

LANGUAGE USAGE The code readability and syntactical practices are generally good, with a few exceptions. Some issues found:

Naming Conventions: preceding private variables with an “m” is no longer considered best practice. An underscore is still used. The code is inconsistent in this manner between files, though the files themselves are generally consistent throughout.

Commenting: Xml­based summary commenting is used inconsistently, being present on some public methods but not others.

PAGE 6 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 7: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

Commented Code: commented code is present in places; typically this is frowned upon for code that ends up in the repository

Unnecessary null­checking in places, and missing null­checking in others Multiple Regions with the same name in the same file Inconsistent use of “var” keyword Some methods appear to be overly long; long methods indicate that their functionality can be further broken down

into more methods There are some dated practices throughout. However in a codebase this large, that can often be the case if development spans years; best practices shift and change over time.

WPF VIEWS WPF Views dictate the layout of a given screen or screen part. In MCAPS4, many of the views in the system are overly complex and should be broken out into many, smaller, views and viewmodel pairs. Many of these views are over 2,000 lines long. In addition, many of the view items have hard­coded widths. If there is ever a desire for this app to work well in a resolution­independent manner (i.e. scale well on smaller/larger screens), a very large refactor would need to occur. Lastly, the application has never been setup for localization. If support for non­English languages is a desired feature this could be a significant effort.

WPF STYLES In a WPF application, styling is code that help define how UI elements look. Styling is a very big concern because there are many ways to do it wrong and end up with a maintainability problem long­term. In MCAPS4 there are instances where it could be done better, but in general it looks workable.

UNIT TESTS Modern Applications often feature Unit Tests, which are small tests that run against discrete pieces of application code to ensure that the application code does what it is supposed to. Unit tests help protect against regression issues in the development life cycle. This is especially useful, even critical in large, complex applications. The act of creating an application that can be unit tested often helps developers create decoupled code from the start. The MCAPS4 codebase contains no unit tests. Adding unit tests to an existing application this large and complex could be a significant effort.

PAGE 7 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 8: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

DATABASE ARCHITECTURE The test database we were given contains 262 database tables and 1,434 Stored Procedures.

Tables The number of tables speaks, to some degree, to the complexity of the application and the problem domain as a whole. Without further domain knowledge, it is difficult to say if the database architecture can be trimmed somewhat. It does suggest that there may be opportunity to split this database into multiple databases with different concerns (for instance a database for application­specific concerns like Users and Tasks and a different database for case­specific concerns). In looking at the tables themselves, they appear to be well­designed with consistent naming conventions, ID and primary/foreign key practices. The data types used appear to be large enough to be flexible while small enough to be efficient. Use of GUIDs (Globally Unique Identifiers) for primary keys is a good, safe alternative to integers. Aside from the sheer number of tables, the biggest concern here from a maintainability perspective is that some of the table names are pretty vague. Some examples include Lookup, FormatCode and Variable. Some are confusing without specific domain knowledge, such as: MS60911, Evidence701, ICR.

Stored Procedures Use of Stored Procedures (or “Sprocs”) in general can be problematic for a few reasons:

1) Each stored procedure is a file that contains code in the form of database scripts. This is a lot of code that needs to be maintained

2) Application and business logic written in C# can be unit tested if architected correctly (see above). Application and business logic in a stored procedure are more difficult to unit test properly. This is one of the big reasons why stored procedures have taken a backseat to ORMs (Object Relational Mappers).

That said, there can be performance increases to using stored procedures as compared to ORMs like Entity Framework, if those stored procedures are well written. Ideally, when the decision is made to use stored procedures, it is best to keep business logic out of them as much as possible. In the MCAPS database, the number of stored procedures is, to some degree, going to be a function of the number of tables, however there appear a couple hundred more stored procedures than is strictly necessary for CRUD (Create, Read, Update, Delete) operations on 262 tables. That indicates that a number of stored procedures exist for specific application or business logic purposes. We see this is true in the example in the next section. This can be an indicator of a maintainability problem. The alternative is implementing a true IRepository pattern throughout the code, complete with model­driven CRUD methods. This would greatly reduce the amount of coupling between repositories and individual models, as well as allowing for the deletion of literally thousands of lines of code. Note: The MCAPS Database project might be an attempt at creating a scenario where this could happen, but it doesn’t look complete and/or widely used.

PAGE 8 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 9: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

PERFORMANCE

APPLICATION PERFORMANCE Low­fidelity performance testing was done, as time permitted, on a few aspects of the application that were identified as trouble spots. Below is a graph that shows the processor time (top, red) and thread count (bottom, green) for the following behaviors: application startup (1), switching to the Case tab (2) and switching to the calendar tab (3).

It should be noted that performance analysis was done on a Debug build of the application. That, and the actual act of profiling the application both have the effect of making the application times look much slower. So, while start­up looks like it took 45 seconds on the graph, this time would be faster in an unprofiled, Release build version. It should also be noted that we’re using a test database provided by the current development organization. It is likely that a larger, “production” database will yield different results.

What this graph shows is that startup takes a lot of processor time (1), going back down to zero around the 45­second mark. Just after one minute there are two more peaks, opening the Case tab (2) and opening the Calendar tab (3). This shows that relatively speaking, a lot more is going on in Startup and opening the Case tab. In doing some SQL Profiling, it appears some of this lag can be accounted for in database Stored Procedures. There are 31 stored procedures run during the startup sequence. These stored procedures are ranked according to how long they took to run (we have included the run­times for the top 10). Combined, they account for 2.567 seconds (actual time) of application load time in database activity.

usp_GetCriminalCaseTabsInfo (611ms) usp_GetOfficePersonnelInfoList (501ms) usp_GetLookupInfoList (414ms) usp_GetOfficePersonnelInfoList (292ms) usp_GetInCustodyByIsClosedInfo (133ms) usp_GetCalendarMainByOfficePersonnelIDInfo (126ms) usp_GetJOrgPersonList (101ms) usp_GetUserInfoByLogin (90ms) usp_GetJOrgList (68ms) usp_GetLookupInfoList (42ms)

PAGE 9 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 10: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

usp_GetNJOrgPersonWithDetailsList

usp_GetInCustodyByIsClosedInfo

usp_GetSubProceduralStatusList

usp_GetOfficePersonnelInfo

usp_GetAppStartupInfo

usp_GetJOrgList

usp_GetNJOrgList

usp_GetJOrgList

usp_GetInCustodyByIsClosedInfo

usp_GetCalendarReoccurringDefinitionList

usp_GetConfigurationList

usp_GetDivisionList

usp_GetJOrgPersonList

usp_GetUserInfoByLogin

usp_GetNJOrgList

usp_GetConfigurationList

usp_GetSubProceduralStatusList

usp_GetAppStartupInfo

usp_GetPreferenceList

usp_GetCalendarMainByOfficePersonnelIDInfo

usp_GetPreferenceList

In inspecting this list closely, you can see that some of these are called multiple times. Some of these are called multiple times with different parameters (not shown), which may be perfectly logical. Some, however, like usp_GetLookupInfoList and usp_GetOfficePersonnelInfoList are called more than once without any parameters at all, which means the application is requesting exactly the same data more than once. This would suggest that something odd may be going on and, at the very least, there is room for optimization. As a case study, we took more a detailed look into usp_GetOfficePersonnelInfoList. We saw that this stored procedure has the following description: “Returns the lists necessary to populate the Home Calendar page drop down lists as well as tasks.” Of note:

The SQL is well formatted and well commented The stored procedure creates a temporary table in memory (which can be a slow task by stored procedure

standards, if done improperly) The stored procedure is performing 13 different SELECT operations Five of the SELECT operations use the DISTINCT keyword, which has performance implications The stored procedure is inserting records into the temporary table and then using that temp table to further filter

and join for the results It appears, on the surface, that this stored procedure is 1) too specific to a given task, 2) is attempting to do too much at once and 3) has performance issues as a result.

PAGE 10 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 11: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

SYSTEM ARCHITECTURE & SECURITY While not fully and formally reviewed, our understanding of the System Architecture as it stands now is that the application communicates directly to the database, as follows:

This has a couple of potential problems:

1. A direct SQL Data connection is going to be “chatty” as many queries are run and processed. This means that on poor data connections, performance losses could be exaggerated as the MCAPS4 client makes many calls directly to the database.

2. This setup requires that the users running the client software have direct access to the database. The application

imposes limits on what specific users can do, however with this direct access, someone who knows what they are doing may be able to circumvent the application and perform any operations they wish, directly on the database.

An Alternate Approach An alternate approach to consider is putting an API back­end in between the database and the client. The API can do the heavy lifting as far as data access and distillation and send along just the data the client needs to display to the user.

This would have a few benefits:

PAGE 11 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 12: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

1. Fewer connections and lower byte counts per transaction directly translates to better performance (seen as lower lag between operations), especially on poor data connections.

2. Database access would be limited to the API software, thus potentially mitigating some possible security holes and better adhering to industry best practices.

3. Offloading the heavy lifting to the server means the client application would be “thinner,” meaning smaller downloads/installs and better performance on some workstation computers.

It should be noted that this is a significant deviation from the current system model and may be a costly option to undertake. However in the long run it would be a more sustainable and scaleable model.

APPLICATION INSTALLER There is no application installer at the present time. While not a reflection on the code or architecture, it became apparent in discussion that time spent on an installer could pay for itself quickly in terms of person­hours spent manually upgrading workstations.

USER EXPERIENCE & DESIGN In addition to reviewing the application code, we also were fortunate enough to get a demo of MCAPS4 by an extensive user of the application, Stephanie Nuttall. In seeing the application in action, became clear that portions of the application may benefit from the attention of a User Experience Designer. UX Designers will sit down with users and learn how they actually use the application, and then work with developers to design screen experiences that help users do what they need to do as efficiently as possible. Types of things a UX Designer could help address:

Some common operations in the application appeared to take more clicks than they otherwise should Information Architecture, specifically the organization and layout of information in the application, can be

improved in general The User Interface design is functional, but is dated. Modern­looking applications are possible with WPF and the Windows 10 design paradigm provides an excellent baseline in the hands of a good designer. It is our recommendation that a professional User Experience Designer perform a review of the application.

OTHER SPECIFIC EXAMPLES OF PROBLEM AREAS In reviewing the application, the following specific concerns were discovered.

PAGE 12 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions

Page 13: PHONE (877) 644.6373 CODE AUDIT - MnCCCcalendar.mnccc.org/docs/8874/MCAPSCodeAudit.pdf · Caliburn Micro, one of the more modern libraries, has a concept called View Caching that

File: MCCC.MCAPS.Infrastructure.Repository.EChargingRepository Issue: 1,954 lines of manually creating an XML document by hand one line at a time Suggestion: Use a templating language such as Razor to manage this type of transform Issue: 1 method that is 530 lines long Suggestion: Break this into manageable sections that can be easily maintained Folder: MCCC.MCAPS.Infrastructure.Events Issue: 471 files that represent events that can be fired by the system Suggestion: As with the UI components, break these into a component set of logical groupings. Even if they need to exist within this project/namespace, group them together so a single one is easy to find and maintain. File: MCCC.MCAPS.Infrastructure.AssembleReport Issue: This class generates files/reports for export out of the system. Every report is generated by hand, line by line, and then saved. This file is 8,708 lines long. Suggestion: Use a templating language such as Razor or a CSV library to manage this type of transform

PAGE 13 OF 13 CODE AUDIT - Reston Association- Monthly Maintenance/Feature Additions


Recommended