Rob Kraft's Software Development Blog

Software Development Insights

Archive for the ‘Coding’ Category

The Elements of Software Development

Posted by robkraft on August 18, 2021

Elements of Software Development

Successful software products and solutions rely on much more than the programming source code put into them.  The elements attempt to identify all the factors that affect the outcome of a software development project.  The value of recognizing each of these elements is to help those involved in a software development process recognize that many elements influence the production of quality software, and each of these elements should be evaluated if you desire to improve your software product and software development processes.

Most people accept, as self-evident, that any process has room for improvement.  The CPI (Continuous Process Improvement) mindset encompasses many programs and frameworks that accept that people can always do better and can systematically attempt to do so.  If you agree that improvement is possible, it follows that you also recognize there are many areas in which improvements can be made.  We can’t make all possible improvements simultaneously, therefore we must select a few things to improve and start those before identifying and working on other areas of improvement.

The elements give us places we can look to consider making improvements.  We will find that it is easier to make improvements in some of the elements than in others, but we should also consider which improvements provide the best return on investment (ROI) when undertaken.  We hope practitioners will examine each of the elements and consider if changes could be made that would improve their software development process and product, and direct their energy to those changes that will most likely be successful and provide the best ROI.

The elements of software development are the things that influence how software is developed.

Each element has been assigned a category, either Product, or Process, or People.  Elements assigned the people category are elements that affect the development of people.  When you make a change to one of the people elements, you are usually making a change that you hope will improve a person or people.  When people have better training, experience, tools, and workplace satisfaction they are more likely to produce better software.  Elements assigned the process category are elements that are used to produce the product, but that are not present within the product delivered to the client or people that use the product.  Agile methods and DevOps are two very notable elements assigned to the process category that have a significant impact on the successful delivery of a quality product.  Of course the elements of the product category include those things the customers interact with, including training and support along with the quality of the software.

Product is what the customer is buying; process is how that product is created; people are those using the process to create the product.

On nomenclature:  The word element and category are lower case for a reason.  There is nothing special or significant in the choice of these words.  The word element was selected primarily because it is less used in software literature than many synonyms that could have been used such as component, factor, feature, or module.  Likewise, category is used extensively in the domains of many fields, but in this article it is a simple term used for grouping some similar elements.

The Software Development Life Cycle (SDLC) has long been considered the list of steps followed for the production of software.  The elements makes no change to that.  The elements identify additional factors that influence how software is produced and that affect the success or failure and quality of the software.  Nine of the elements are noted for having a close correlation in meaning to a step in the SDLC.

SDLC is the name for the process we use to get from Idea to Solution.

The first purpose of the elements of software development is to help us identify where we might spend our time to make improvements.  The second purpose of the elements of software development is to help us identify the current context in which we develop software so that we may make better selection of practices and processes that will lead to success.  There are hundreds of practices and processes to choose from to use during software development, and much debate about which practices and processes are best.  The truth is that the value of any specific practice or process depends a lot much upon the context in which it occurs.  Perhaps this is best understood from this example:  Some software developers believe strongly in CI/CD and believe that all development teams should make it a goal to deliver software continuously.  However, other software developers work in a context where that is not possible.  For example, continuous delivery of software embedded into gyroscope controllers on a Mars rover craft is impossible.  Even for many contexts where it would be theoretically possible to apply CI/CD, the benefits and risks are not worth the cost of doing so.

The value of a practice or process must be considered within the context in which it is applied.  Of the twenty-five elements, all but three contribute to the context in which software is developed.  Therefore, when we consider the use of a different process or practice, we should consider our context as a factor that may make that process or practice successful.  Many software development teams have adopted the Scrum methodology in an attempt to improve their software development.  Unfortunately, the adoption of Scrum has not been successful in every case.  But why is that?  Is it because they are doing Scrum incorrectly, or is it because Scrum is not a good practice for their context?  That is a difficult question to answer.  Unfortunately, a few people dogmatically believe Scrum should always be used by all teams, and that could be based on their own lifetime of experience, which could be all within similar contexts.  These people then may continue to push Scrum even when it is not the best choice in a different context.  This is the outcome we hope to avoid when practitioners consider the context into which they are attempting to apply a practice.

The context for software development for a team reflects the collection of twenty-two of the elements.  The context is the interaction of these twenty-two elements.  The implication is that you should ask if the practice you are considering to adopt is a good practice for your context.  Is it a good practice that aligns with your choices for each of the twenty-two elements that apply to context?  A few examples of processes and practices, Scrum and CI/CD, were already mentioned.  Other examples of processes and practices include Test Driven Development (TDD), Pair Programming, Unit Tests, Automated Builds, Kanban, Retrospectives, Estimates, Metrics, WIP Limits, Story Points, StandUp Meetings.  There are many more.

The hope is that we can use the identified context to make a good selection of practices.  Here is an example that considers just a few of the context elements along with the question, “Should we develop software using TDD?”  If the “Team Composition” is “junior developers”, and the “application architecture/design” is “unknown”, then asking them to use TDD when they have not done so before may be very valuable to achieving good results.  But if the “Team Composition” is “senior developers”, and the “application architecture/design” is “well known”, then asking them to use TDD when they have not done so before may be detrimental to the results.  TDD, or any other practice or process, is not inherently always good or bad, but these patterns and practices work better in some contexts than others.

Context is the collection of factors that influence the choice of best practices for your software development processes.

The twenty-five elements of software development are used by most software development teams, but not all.  For example, software developed by a single person is unlikely to have a “Hiring Process” element.  However, for each of the twenty-five elements, a software development team made a choice about what to use within each element.  Here are a few examples.  For “Architecture”, the choice could be a web application, desktop application, embedded application, or another architecture.  For “Project Management”, the choice could be Scrum, Kanban, Waterfall, or another process.  Every software product under development is being developed in a specific context, and that context affects best practices.  Many people probably also understand that the context is rarely static.  A team that is developing an application using one process many also be transitioning to developing the application using a different process.

As mentioned previously, it is probably counter-productive, destructive, or simply impossible to systematically make changes to all the elements of your software development at the same time.  You must select some to begin improving, which means you must choose those that are most valuable to change first.  Even when someone can show you that there is value in changing the way you handle one of the elements, you might not begin making that change because there are more valuable things to focus your efforts on.  The one limiting factor that all software developers share is limited time.

We have a limited amount of time to spend on creating software and improving processes before the results of our efforts becomes obsolete.  Therefore we must choose wisely how we spend our time.  What changes will produce the most benefit, do the least harm, or introduce the least risk?

The elements of software development are shown in a list that includes some questions related to each element to help developers understand what they represent.  Future articles will cover each item in more depth.  Another track of future articles will look at software development practices one by one and consider which implementations of each element could be benefit from the practice and which it could be a detriment to.

A PDF version of the content of the images above is available online at https://kraftsoftware.com/ElementsOfSoftwareDevelopment.2021.8.16.pdf

Posted in Coding, Culture, Process, Project Management, Software Development | Leave a Comment »

CI/CD – Is It Right For You?

Posted by robkraft on July 6, 2021

Prologue:  Software Practices Are Only Best Within Specific Contexts

Have you ever attended a conference session with a presenter that is very passionate about a new process?  They believe that everyone should be using the process.  Often, I have doubts that the process will work for my team, but the presenter seems to imply that I don’t fully understand what they are attempting to convey; and perhaps I just need to start trying to make the change to realize the value of it.  While this could be true, I have learned over the years that many people pitching process changes that provided enormous return on value for their software development teams, are pitching solutions that might not work well for other software development teams.  The presenters are not trying to sell me something I don’t need, and they are not being dishonest, they are usually just considering their solution from a single context.   

And what do I mean by context?  A context is the processes, people, tools, networks, languages, deployment models, and culture in which software is produced and deployed.  A practice that is optimal in one context may not be optimal in another, just like the best practices for building a house may differ from the best practices for building a bridge or a skyscraper.  Some aspects of context affect some best practices more than others.  For example:

  • Your deployment model is an aspect affecting the processes you choose.  It is possible to use the CI/CD process when you deploy to a web app, but impossible to use CI/CD when deploying software to chips that are embedded in the engines of airplanes.
  • StandUp meetings might be ideal for a scrum team with all members co-located and starting work at the same time; but a waste of time for a team of four all sitting at the same desk doing mob programming.

This series of articles looks at software practices one by one to highlight what contexts each practice may work well in, and contexts where the practice may not work well, or may even be counter-productive.

Here is an example of a context constrained best practice.  After graduating from college, a developer created static web sites for years, modifying html pages and JavaScript and committing code changes to GitHub while also maintaining a web server and uploading file changes to the web site using FileZilla.  But then he discovered Netlify which uses the JamStack process which makes it incredibly easy to commit his changes to GitHub and have them validated, compiled, optimized, and automatically deployed to the production web site.  Now he is telling everyone they should use JamStack and Netlify for all web development.  And perhaps they should, if they are deploying static public web sites.  But some developers are deploying to internal web sites.  Some developers have database changes and dependencies on code from other teams.  Some developers have mission critical applications that can’t risk ten seconds of downtime due to an error in production.  These are different contexts and the Netlify/JamStack approach may be undesirable for these contexts.

In short, any “best practice” applies within a specific context, and is unlikely to apply to all contexts.  We need to identify the best practices that we can apply to our contexts.  Some people are dogmatic about their ideas of best practices.  They believe a process should always be applied in all software contexts, but personally, I think there may be no software practice that is always best.  I think there are many contexts in which some process recommendations are poor choices.

Subsequent articles will examine processes one at a time, explaining why the processes are poor choices for some contexts.  The list of process recommendations that will be shown to be poor choices in some contexts include the following: Scrum, TDD, Pair-Programming, Continuous Deployment (CD), Story Points, Velocity, Code Reviews, Retrospectives, Management By Objectives (MBO), and metrics.

Main Content: Is CI/CD Right For You?

The acronym CI/CD stands for “Continuous Integration” and “Continuous Delivery” and also “Continuous Deployment”.  Usually, perhaps always, CI needs to be implemented before either of the CDs can be implemented.  CI refers to coders pushing code changes to a shared team repository frequently, often multiple times per day.  In many contexts, a build of the software is started once the push into the shared code base is complete.  In some contexts, builds of the shared repository may occur on a regular basis such as every hour.  The benefit of automated builds is to quickly identify cases in which the code changes made by two developers conflict with each other.

Along with running a build, many CI pipelines perform other tasks on the code.  These tasks include “static code analysis” aka “linting” to determine if the code follows code formatting standards and naming conventions as well as checking the code for logic bugs and bugs that create security vulnerabilities.  Static code analysis may detect if new and unapproved third-party libraries were introduced, or that code complexity levels exceed a tolerance level, or simply if a method has more lines of code within it than is approved by company standards.  If the code compiles and passes the static code analysis checks, it may then have a suite of unit tests and integration tests executed to verify no existing logic in the application was broken by the latest code changes.

CI encompasses two practices; frequent code pushes and automated builds.  Some of the benefits of frequent code pushes include:

  • Developers get feedback more quickly if they have made changes that conflict with something other developers committed,
  • Builds based on the shared repository are less likely to conflict with changes from other developers when the code base the developer is working from is more current and the number of changes made to the code is fewer,
  • Reviewing code of other developers is easier when developers check in frequently because it is likely there are fewer code changes to review,
  • Since code reviews take less time, they interrupt the flow of the developer reviewing the code less,
  • Since code reviews take less time other developers are more willing to perform the code review and are more willing to do it soon.

Some of the benefits of automated builds include:

  • A relatively quick response if code pushed to a shared repository causes a build failure,
  • Relatively quick feedback from static code analysis tools to identify problems,
  • Relatively quick feedback from unit tests and integration tests if code changes created bugs in the application.

CI is very beneficial and invaluable to many software development teams, but it is not necessarily a benefit in all software development contexts.  Some contexts that may gain little value from CI include:

  • When there is only a single developer on the project and a CI environment does not already exist,
  • When developers are exploring a new programming language for development.  In this case, the time required to set up the CI may be more than it is worth for something that might get discarded,
  • When the coding language is a scripting language and there is no compile step,
  • When a team has no automated build currently and creates the compiled version of their product on their local machines to deploy to production.

Should You Make a Process Change?

When evaluating if any process like CI is good for you, the most important factors in making the assessment are:

  • Is it worth my (our) time to implement the process or practice?
  • Will the process improve our product quality?

If the process does not improve quality, which means it doesn’t decrease bugs or decrease security vulnerabilities or improve application performance; and it takes significantly more time to implement the process than it will save by not implementing the process, then you should probably not implement it.

Should You Consider CI?

With this definition of CI and criteria for assessment, I believe that most development teams should consider implementing CI into their development process.

CD Benefits and Drawbacks

The other aspect of CI/CD is CD.  CD stands for either “Continuous Delivery” or “Continuous Deployment” or both.  Both terms imply that successful software builds get automatically pushed into an environment where it can be tested or used, but some teams prefer to use “Delivery” for non-production environments and reserve “Deployment” for the “production” environment.  Also, some teams don’t really automatically deploy the software to an environment after it successfully builds.  Instead, the deployment to an environment requires a button click by an authorized person to proceed.

CD has less adoption than CI, partially because CI is generally a pre-requisite to CD, but mostly because CD is not a good deployment strategy for many software products.  In fact, CD is not even possible for software embedded onto chips and placed into airplanes, cars, refrigerators, rockets, and many other devices.  Nor is CD practical for most desktop applications and applications delivered to phones and other devices through an app store.  CI/CD is most likely useful in the deployment of web applications and web APIs. 

Some of the benefits of Continuous Delivery to a non-production environment include:

  • It forces you to codify everything.  That means you need to figure out how to automate and automatically apply the environment specific configuration values.  You may need to learn how to use containers to simplify deployment and to version control and automate all aspects of devops,
  • It creates possibilities.  For example, once you have taken the time to create a pipeline where your automated build can flow into a deployed environment, you discover you can now easily automate your pen tests and stress tests against a test environment,
  • A developer can test some changes in a deployment environment that they can’t test in the developer’s environment (aka: works on my machine), such as:
    • Changes related to threading behavior in applications,
    • Changes related to users from multiple devices simultaneously using the application,
    • Stress testing the scalability of an application,
    • Testing features affected by security mechanisms such as OAuth and TLS.
  • Developers can get new features into functioning environments faster for the benefit of others,
  • Developers can deploy to testing environments easily without waiting on the devops team or IT team to perform a task for them,
  • It becomes easier to create a totally new environment.  Perhaps you currently have just production and test.  Now you can add a QA environment or a temporary environment relatively easily if all the deployment pieces are automated.

Some of the benefits of Continuous Deployment to a production environment include:

  • Developers can get new features and fixes to production faster.  This is very valuable for static sites.  This is a core feature of most JamStack sites.
  • Developers can deploy without waiting on the devops team or IT team to perform a task for them.

Some of the challenges of Continuous Delivery to a non-production environment include:

  • Applying changes to databases in coordination with changes to code,
  • Interruption of testing by others currently in process,
  • Insuring the correct sequence of deployments when multiple teams are deploying to a shared testing environment and some changes depend on sequence

Some of the impediments of Continuous Deployment to a production environment include:

  • The need for the software to be burned into a physical chip,
  • The need for the software to be published through an app store,
  • The need for lengthy integration testing and/or manual testing before production, often due to the need to insure the software is correct if it is used to keep people alive,
  • The desire by the company to find any problems with the software before customers interact with it.

Should You Consider CI/CD?

Should you adopt CI and/or CD?  That is a question you need to answer for yourself.  Not only should you consider the benefits and value CI/CD may bring to your development process, you should always also consider if adopting a process is more valuable than other changes you could make.  Just because we recognize the value in implementing a specific change doesn’t mean we should implement it right away.  Perhaps it is more valuable to your company to complete a project you are working on before implementing CI/CD.  Perhaps it is more valuable to wait six weeks for the free training sessions on TeamCity and Octopus Deploy to be available if those are the tools you are considering to use for CI/CD.  Perhaps you are considering moving from subversion to git.  If so, you should probably make that change before you build a CI/CD solution, otherwise you may need to rebuild your CI/CD pipeline completely.  Also, going from manual builds to CI/CD is unlikely to be something completed in a short time frame.  It is something you will progressively implement and adopt more aspects of over time.

I believe that most development teams should consider implementing “Continuous Delivery” into their development process.  “Continuous Deployment” to production is probably primarily of value to teams deploying static web sites, and maybe a few sites with small amounts of data or unimportant data.

Posted in CodeProject, Coding, Dev Environment, Process, Software Development | Leave a Comment »

An Example of Upgrading Code From Average to Excellent

Posted by robkraft on June 13, 2021

Average programmers get the job done.  Excellent programmers get the job done too, but the code of excellent programmers lasts longer and is easier to change to meet future requirements.  Below is an example of upgrading average code to excellent code.

Our team decided an application could benefit from caching some data in our .Net application.  We selected a caching framework with a good reputation and implemented it in one of our business objects.  Here is the code:

private static IAppCache _cache = new CachingService();
public static IList<Zone> AllZones
{
    get
    {
        return _cache .GetOrAdd("zones", () => ZoneManager.LoadAll(), new
            DateTimeOffset(DateTime.Now.AddHours(1)));
    }
}

The code worked and we noticed a performance improvement in our Zones class.  The code was easy to implement.  We decided we would implement something similar in several other classes.  However, the above code is just “average”.  What I mean by that is while “it works”, it could be made better.  Allow me to talk through many of the considerations carefully.

  1. If the code solved a problem and we desperately needed to get it into production right away to keep from losing thousands of dollars per hour, then we should probably deploy it right away.  The business need is more important than the developer’s preference for robust code.
  2. If this was the only place in the application that would need this type of caching logic and it is working well, then the code is probably “good enough” and needs no further consideration or enhancement.
    1. In fact, if this code works as is, and would never need to be modified again, spending additional time to enhance the code (from good to excellent) would actually be a failure.  It would be a waste of time, assuming that the developer(s) involved had alternative activities they could engage in that would add more value to the software or the developers skills than refactoring the above code.
    2. If the above code exists specifically for a short-term project, and it will be deleted and no longer used within a week, and refactoring would not improve performance, but would just make the code easier to maintain in the future, but the code really has no future; then refactoring the code is pretty much a waste of time.

In our application, the above caching code was the start of a pattern for caching we wanted to implement in other business objects.  Whenever you are starting some code that will be the pattern by many developers across the code base, you probably want to think about improving the code in the following ways:

  1. Make the code as easy to implement in each place as possible.  That means:
    1. minimizing the references you need to add for each implementation;
    2. minimizing the properties and methods and supporting features you have add each time you use it;
    3. minimizing the code changes you need to make as you copy/paste it from one place to another.
  2. You want developers to fall into the Pit of Success.  This means you want to make it easy for everyone using the pattern to get it right.  The fewer changes they have to make, and the more obvious those changes are, the more likely the other developers will successfully implement similar code in other places.

We were aware that the framework we used for caching could change.  We started with a framework called LazyCache that uses the IAppCache interface and CachingService, which you can see in the code above.  But what would happen if we decided we needed a different caching framework in the future?  We might have to go back to each business object and change the interface we used, and probably replace CachingService.  Can we refactor this code to make it unlikely the code in the business object needs to change if we decide to use a different caching technology such as Redis?  I believe the answer is ‘yes’.  Our goal then becomes the following:

  1. Move all the code specific to our caching technology (LazyCache in this story) into a separate class, so that our business objects are totally unaware of the technology used for caching.
  2. Pass all the values and method needed for the caching feature from the business object to the new caching class we create.
  3. Minimize the things we need to pass to the caching framework to make the code easy to implement in each business object.
  4. Write the caching class in a way so that it also does not need to know much about the business objects that it is caching.  Make sure that it does not need to reference those business objects.
  5. Write code so that the caching class does not need to be changed when it gets used by additional business objects.  It can become a “black box” to future developers.

The revised code in the business object looks like the following:

public static IList<Zone> GeoZonesFromCache
{
    get
    {
        return CacheManager.GetOrAdd(CacheManager.ZONES, () => ZoneManager.LoadAll());
    }
}

Notice that it no longer has any reference to the caching service.  This should allow us to change the way the data is cached from using LazyCache to some other Caching framework including caching services like Redis Cache without needing to modify each business object.  We pass the minimum information which includes the name of the cache (which is a ReadOnly string named CacheManager.ZONES), and also the function to run (ZoneManager.LoadAll) if the cache is not already populated.

We did have to write more code in our CacheManager.  Here is the code:

using LazyCache;

namespace MyApp
{
    public static class CacheManager
    {
        private static DateTimeOffset GetCacheDuration(string cacheType)
        {
            return new DateTimeOffset(DateTime.Now.AddHours(1)); 
        }

        private static IAppCache _cache = new CachingService(); 

        public static IList<T> GetOrAdd<T>(string cacheType, Func<IList<T>> itemFactory)
	{
	    return _cache.GetOrAdd(cacheType, itemFactory, GetCacheDuration(cacheType)) as IList<T>;
	}

        public static readonly string ZONES = "zn";
    }
}

In the code above I include a using statements, for LazyCache.  This is the only class in the entire application that references LazyCache.  If we decide we want to replace LazyCache with Redis cache or some other cache then this one class should be the only place in our app where we need to make a change.

Is the code that we wrote perfect?  The answer to that is definitely ‘Maybe’.  We can’t know if existing code is perfect until time has passed and we determine if it met our needs.  I believe that the code has to meet these criteria to be considered perfect:

  1. If the code never needs to be changed, then it was perfect,
  2. If the code does need to be changed, but it is easy for the developer to change in order to adapt to a requirement change, then it could still be considered perfect when originally written, especially if the changes are isolated to the CacheManager class and don’t need to be made in each business object that uses it.
  3. If changes are needed in each business object, but the changes are easy to implement and were not foreseen when the code was first written, then you could still consider the original code to be perfect.  For example, perhaps some business objects need to pass the cache duration into the CacheManager service.  Assuming that code is easy to implement, and it was not originally expected and coded for, then the original code could still be considered perfect. 

Some of you may identify that improvements to the CacheManager are still possible, and that is certainly true.  One improvement would be a change to make it easier to write unit tests for the business objects using CacheManager.  The code I have above is hard-coded to use the “CachingService”.  It could be helpful if the “CachingService” could be mocked away in unit tests, especially if you replace the CachingService with Redis Cache.  Fortunately, given that the caching code is contained within a single class, it would be fairly simple to change the CacheManager to use an IOC framework.  I won’t delve into that here other than to point out that part of writing excellent code might include the ability to unit test that code you have written.  I will also point out that the refactored code (from “Average” to “Excellent”) makes the writing of unit tests to test the CacheManager itself easier.

You may also notice that the code contains no error handling.  I did not include error handling because it would add clutter that is irrelevant to the topic of this article, and also because some programmers may prefer errors to bubble up the call stack to be caught elsewhere in the application.

To recap this article, if you want to go from being an average developer to an excellent developer in a scenario like this you should do the following:

  • Before writing code, first identify if there is already a solution to the problem in your code base and determine if you can reuse the same solution.
  • When you are writing code, ask yourself if part of the code could be re-used in other places in the application, or perhaps in the future.
  • Take some extra time to write the code in a way to make the pattern easy to implement correctly in every place it will be implemented (or at least in many of the places).
  • Write the code in a way to minimize the need for modifications to each business object if changes to the service being implemented are needed.
  • Make the places where the pattern is implemented unaware of the details of how it is implemented.  In other words, the business objects have no idea what caching technology is used and won’t need to be altered if that caching technology is changed.
  • Make the pattern unaware of the specifics of the objects that are using it.  In other words, the CacheManager does not need to be able to reference and understand the business objects that are calling it.  There is no dependency there.
  • Don’t pass hard-coded strings.  Use an Enum or string constants.  This allows you to change the string value in a single place if you ever need to do so, and, more importantly, insures there are no string typos made.  In the class above, this was done for the CacheType (CacheManager.Zone).  We could have passed a literal string “zn” into the CacheManager, but we anticipate adding logic, perhaps a switch statement based on the cacheType to obtain the duration for the cache, which means we would have a second place (the switch statement) also with a hardcoded string of “zn”.  By using a readonly variable we eliminate the risk of typos for that string.

This is not an article about caching.  This is an article about taking code that is average and making it better, using the implementation of some caching logic as an example.  Some of you may notice that our change to make the code better is also an example of “Separation of Concerns”.  This is true, but the article is not about “Separation of Concerns”, it is simply about writing  better code.  Finally, I will point out that this example is also an example of the “Façade” pattern, but again, this is not an article about the “Façade” pattern, just an article about better code.

I hope this article helps some average developers along their journey to becoming excellent developers.

Posted in Code Design, CodeProject, Coding | Leave a Comment »

Questions Newly Hired Developers Should Ask To Become Contributors More Quickly

Posted by robkraft on May 27, 2021

In my last article (https://csharpdeveloper.wordpress.com/2021/05/24/how-companies-can-facilitate-the-onboarding-of-entry-level-developers/) I wrote about things a company could do to improve the onboarding experience for entry-level developers.  In this post I offer some questions that newly hired developers can ask to improve their own onboarding experience.  Not only do I suggest that you ask these question, I think you should actively seek the answers to these questions if you have idle time.  Knowing the answers to these questions will improve your understanding of how things are done at the company and impact how you write code and spend your time in development.

  • What do I need to do to be considered a contributor to the company?
    • One of your employer’s biggest concerns is the unknown number of weeks or months it will take before you provide more value to the company than the cost of your salary.  No matter how talented you think you are, you almost certainly are costing the company more than you are worth for the first few months you work there, if not longer.  And the reason for this is because a senior developer could complete all the work you did in your first two months in one-tenth of the time and with higher quality.  So, if that senior developer has to spend half of their time during your first two months assisting you, then the company is going to be nervous that you will continue to cost them more than you are worth.  However, take heart in understanding that your employer hired you knowing there would be an upfront cost, but in the hopes that you would soon be able to contribute more than you cost, and be able to contribute without requiring a lot of time from the other developers.
  • What percentage of my time will I spend using my JS/TS skills, my server-side skills, my database skills, (the skills that you hope to spend time on improving/learning)?
    • This question really should be asked before you get hired unless you really need a job soon.  If you are craving to write TypeScript code but learn you will be tasked with writing database SQL for the next year, then you should definitely let your employer know your preferences because they may be able to make adjustments to improve your employment satisfaction.
  • Who will be using the software I work on?  Is it external customers or internal employees?  Are we developing applications for other businesses?
    • Most entry-level developers I hired rarely asked such questions, but I don’t think less of them for not asking.  The reason I think newly hired developers should ask these questions is because it helps give the developer a better understanding of how the software works and is deployed.  It helps the developer correctly assess the trade-offs between application concerns such as security and performance and the impact and risks of making mistakes.
  • How is the software that I will be working on deployed?  Is it “in the cloud”?  It is on premise?  Is it web apps or desktop apps or phone apps?
    • Like my note on the previous question, this helps developers assess impact and risks of making mistakes, and also understand what technologies they may need to learn.
  • What is the process for our source code to get to deployed?  Do we commit to a source control?  Do we manually run build and deploy tasks?
    • In some companies, developers write code, check in into a repository, and then forget about it.  In other companies the developer guides the code all the way into the production environment.  The answers to these questions will help you understand what is expected of you and your role in the process and identify some things you need to learn.
  • Are there unit tests or static code analysis or other steps in the build pipeline?
    • Companies with more highly evolved software development practices often have static code analysis and unit tests.  If your company does not have them, this identifies an area where they could possibly improve by adding them.  If they already have these processes, then you should probably learn how to use them and gain their advantages.
  • If there are tests, how do we write and manage them?
    • Unit tests provide a lot of value for teams that continue to work on and evolve a software product.  If your team is already using them, you should learn how you can add your own unit tests as part of the first lines of code that you will write yourself.
  • Are there database changes that might accompany our code changes, and if so, how is the deployment of the two together managed?
    • Many software products store data in databases, and often those are relational.  If you make code changes that affected how the data is stored, then the change to the data store needs to be migrated into production along with your code changes.  This can be challenging in many environments so you want to understand the impact and how it can be managed.  You may decide in some cases that you will write your code in a different way to implement a feature just so that you can avoid a database change.
  • Is there a QA/Test environment that we can deploy to, and is there staff to test our changes?
    • This helps you understand how much responsibility you have for testing your code changes.  Not that you shouldn’t always test your own code changes, but often a change you make could affect many scenarios, and a QA team can help reduce the time you need to spend testing.  When a QA or Test environment exists, it tells you that the company is fairly concerned that bugs don’t get introduced to the production environment.
  • Who do I work with to review my code changes and to guide me toward writing good code?
    • A specific single person signals to that person that they are expected to work with you and therefore will dedicate time to do so.  When there is “shared” responsibility, team members often hope that someone else on the team will help you because each team member is usually already very busy; and they each assume someone else is less busy than they are. 
  • How do I receive the tasks that I am going to work on, and how does the team track my status on those tasks?
    • Most software development shops use a white board or some task management software.  There are many free task management tools on the Internet like Trello, but most teams will have something more sophisticated.  Learning how to correctly use these products is important for you in learning how to manage your work and to help your team members see that you are contributing.
  • How do the users of the software know all the features we put into it and what bugs exist and what bugs have been fixed?
    • Some products, especially software for internal employees, may not track this at all; but software for sale that is used by external customers probably does.  As you fix bugs and add features those usually need to be shared with customers and understanding how that process works will help you contribute good explanations and information to the customers.
  • Who do I contact for non-technical questions about how features in the software should work?
    • Hopefully you have a mentor to help you write code, but you often need to talk to the users of the software, or a representative of those users, to better understand exactly what they would like to have done, or to collaborate with them about the costs of what they asked for and alternative ways to solve their problems.
  • Is there documentation for users of the software that I can learn from?
    • This is a great way for new developers to get up to speed more quickly on what is expected of them.  Seeing the software from the end user perspective will help you understand what needs to be accomplished in the code you write.
  • Is there documentation about the software architecture and coding guidelines?
    • Internal documentation can help you make appropriate decisions, not just about formatting but also in helping you to identify that some problems have already been solved and you can, and should, re-use the existing proven solution.
  • Can I install software on my computer, or do I need to ask permission first?
    • Before installing software, get permission.  Some companies provide a location with tools already approved for use.  Many companies do not want you to download software from the Internet due to the risks that the software may contain malicious code.  They will desire to first approve it.  You don’t want to be the person that downloads the malware-laden software component that infects the company’s network with ransomware.
  • Are there policies I should follow before adding third party dependencies or components to the software we are writing?
    • Although a StackOverflow post may show how easy it is to include a third party JavaScript library in your web page to solve a problem; it might not point out that the license requires that the JavaScript library only be used in open source projects and any software that uses it should be considered open source.  This can lead to lots of legal hassles.  Make sure that you approve third party frameworks and tools that you use and honor their license agreements so that you don’t get your employer into expensive legal trouble.
  • What are the security threats I should be aware of when writing our software?
    • If you are asked to import an XML document into an application and process it, you should probably learn how concerned you should be with making sure that XML document does not contain malicious script that could do harm to the computers on which your code is installed.  XML documents are just one example; many inputs and processes can introduce security risks.  Learn early what the security threats are and also how your team correctly addresses those threats so that your code doesn’t open the door to malware.
  • Does our software need to adhere to compliance guidelines such as SOX, PCI, or HIPAA?
    • Like addressing security threats, some of the code we write, particularly some of the design and management of sensitive information like passwords and credit card numbers, has to be handled with extra care.  It is likely that good practices have already been identified and you can borrow code from elsewhere in your applications to handle compliance guidelines; and it is best to learn the right way to do those things before writing code that just works.
  • Will I be exposed or working with any sensitive data and how should I handle it if I will?
    • Patient and customer data sometimes ends up in test databases so that developers have real data to test with.  However, you should take care with the data and make sure it is not shared in printed pages, or on test web sites, or exposed to other people that have not signed the waiver that they will treat the data as confidential.  Understand that some data you are dealing with should not be discussed outside of your business context.

Posted in Coding, Software Development | Tagged: , | Leave a Comment »

How Companies Can Facilitate the Onboarding of Entry-Level Developers

Posted by robkraft on May 24, 2021

Despite a shortage of software developers, entry-level developers can tell you that it is difficult to get hired.  Companies are often reluctant to hire entry-level developers for several reasons that include:

  • They don’t want the risk that an entry-level developer may not have the skills to do the job.
  • They don’t want to invest in bringing an entry-level developer up to speed and then see the developer go to work for another company.
  • They don’t want to pay for the time it takes for entry-level developers to become producers instead of costs.
  • They don’t want to lose productivity of current staff devoting their time to bring entry-level developers up to speed.

Development teams also find it challenging to provide tasks for entry-level developers to work on because there are so many things an entry-level needs to understand before doing any coding. A lot of that is the processes surrounding coding and how those processes are performed in the organization.  Below is a list of items that many companies want developers to understand.  Often only the coding items were part of the training the developers received in school.  Companies want a developer that:

  • knows what IDE to use, how to install it, open it, update it, and be productive with it,
  • understands the technologies used by their app in order to get things done:
    • The code language, UI language, data stores, best practices, frameworks, and IDE,
  • knows how to test their code locally,
  • knows how to commit code changes to a repository and update from a repository,
  • knows how to use repository tools to review other code and find code changes,
  • can write unit tests,
  • can start and run unit tests locally,
  • proceeds cautiously at first, not checking in changes without being certain,
  • will not check in code changes to the production pipeline accidentally,
  • understands there is a build process, and be able to run a build on their own,
  • understands the process of how their changes get deployed or used,
  • understands there is a production build and how to initiate it,
  • understands there is a way to deploy for QA/Test (maybe),
  • understands they may be able to deploy directly to production,
  • can find the task management system that has the list of tasks and features and bugs they are to work on,
  • can manage their own tasks on the task boards,
  • knows who to talk to for any task requirements as well as task priority and also if the task is right/ready for them to handle,
  • tracks their time – how much are they spending on each task,
  • can assess what is a priority, or who to ask to get that answer,
  • understands the business domain and what the software “does”,
  • understands the development priorities (security or performance or maintainability or customer satisfaction or just functional),
  • follows the patterns already in use in the code for solving problems,
  • knows how to use our Requirements and Design tools and processes,
  • gets to work on time,
  • is focused on their work during working hours,
  • is eager to learn,
  • is friendly with everyone.

When a company commits some time to building a good onboarding process for new developers, they can greatly facilitate the onboarding process and make it less difficult to hire an entry-level developer. 

  • Create documents and videos of the applications the developer will be working on
  • Create documents and videos of your software development processes
  • Assign each new developer a contact person they can go to for any question.  If you are hiring several developers, ideally each contact person will serve that role for just a single new developer.  Also, the contact person should be someone on the same team that is very accessible to the new employee.
  • Schedule some one on one time for each new developer with each team member.  Often, you can use this time for an existing team member to share knowledge about the company and software with the new developer.
  • Prepare their computer, physical environment, and computer software before they arrive for their first day.  Make sure the application software, and unit tests if applicable, can run successfully on their computer.  Have all of their security accounts ready for use.
  • Have mentors reserve time to spend with new developers almost each day for the first two weeks.  Don’t just hope to “squeeze it in” as needed.
  • Remind existing team members to contact the new developer(s) when they are about to perform a task or process that the new developer needs to learn so the new developer can join them as they go through it.
  • Put off some simple fixes/enhancements on your task board for a few weeks to reserve them for the new developers to do.  Give the new developers a chance to commit a real code change on their first day.
  • Finally, create an onboarding checklist with links to videos and documentation about each item on the checklist.

Here is an example of an onboarding checklist in a google document: https://docs.google.com/document/d/1K5jw1OgQDbLiXt9UvLR9Qnm5Pj9fWj-brp6_FiTUWJw/edit?usp=sharing

If you want a faster start for your own onboarding checklist, I recommend you make a copy of this Trello board and customize it for your own company: https://trello.com/b/h9eTMg4E/onboarding

The way I recommend using this Trello board, is to make a column on it for each new hire.  Each employee can work their way down the board, marking items done on checklists and changing the “Labels” on a card when it is completed.  Many items on this board anticipate that a mentor will work with the new employee to discuss the item (cards with the “Mentor” label).  Other cards have a label named “Complete Independently”.  Of course there is still a lot of work for you to do in preparing documentation and customizing the board for your own development shop, but hopefully this helps you get started.

Posted in Online Resources, Resources and Tools, Software Development | Leave a Comment »

Git for Microsoft Access Databases

Posted by robkraft on May 21, 2021

I wrote about this project previously (Track Changes to Access Form Properties in Source Control (Github) « Rob Kraft’s Software Development Blog), but am happy to share a more complete solution. If you would like to have Source Code Control such as Git or Subversion or TFS to track all the changes to a Microsoft Access database, the code in the github repo mentioned below has the code you need. This code is free for you to use in any respect (MIT license). Just copy the code into a module in your Microsoft Access database, run it, and it will export everything.

By everything, I mean it will export the following information from your Microsoft Access database into files:

  • Code behind Forms
  • Code behind Reports
  • Code in Modules
  • Code in Classes
  • Properties of Forms
  • Macros
  • Properties of Reports
  • Table Definitions
  • Queries
  • Database Option Values
  • Database Property Values

You can get the latest version of this code https://github.com/RobKraft/AccessUtilities

Posted in Access, Coding | Leave a Comment »

Efficient Software Development Surpasses Both Waterfall and Agile Development

Posted by robkraft on May 10, 2021

A product owner asked a developer to add a date picker to the web site in place of a text box. The product owner said it would be nice if the calendar just displayed the five weekdays. The developer knew he could add a date picker but didn’t know if he could exclude Saturday and Sunday from the calendar. He didn’t find any options in the date picker control to exclude the weekend, so he created a new control. It did not render as well across all browsers, and behaved a little quirky sometimes, but it showed only weekdays. This took the developer two weeks to complete, after which he showed it to the product owner. She was not happy with the rendering problems and was very disappointed to learn it cost two weeks to develop. The product owner said she would rather have a control that worked better even though it included weekends, especially if that control only cost a few hours to implement.

The parable tells a tale of software development. It is a sad tale, and a common tale. Many would consider it an example of a project failure. The product owner paid more money than expected for a solution that was not as good as she hoped it would be. This type of problem occurs often in waterfall software development, but it also occurs in Agile software development.

Yet, this problem could have been prevented. The developer and product owner should have communicated more frequently. The product owner should have made it clear that she would like a calendar that excluded the weekdays, but only if it could be completed by adding no more than two additional hours of development. And the developer should have understood that the business is usually willing to settle for less than the asked for if the price of getting exactly what they asked for increases the cost exponentially.

Teams that desire to develop software more efficiently will identify this communication problem and make attempts to reduce the chance it will happen again on future projects. The teams will do this as part of their goal to improve their processes, not because the Agile principles provide this guidance. Software developers should strive to develop software more efficiently, and if following Agile principles helps facilitate that improvement then software developers will follow the Agile principles, but it is important to avoid putting the practice of following Agile principles ahead of efficient software development. Agile principles are a tool we can use to develop software more efficiently, but Agile principles are not the goal of our software development process. Great software developers don’t care if someone considers their processes to be agile or not agile, as long as they are efficient. I feel it is important to stress this last point, because it is the key takeaway from this article: Our goal is not to become an Agile software development team; our goal is to develop software more efficiently.

Developers that already practice Agile development may recognize that the characters in the parable were not following Agile principles, and if they had done so, they would have experienced better outcomes. That is certainly true if the teams were following the principles of Agile, not just some of the common practices. Too often, companies, project managers, scrum masters, and developers adopt practices such as “Daily Standup Meetings”, “Two-week Iterations”, “Retrospectives”, and “Measurement of Velocity” and believe that makes them Agile. But none of these practices would have solved this problem. Following these practices does not make a team is Agile, nor is being Agile the goal. The goal is efficient software development. Agile principles can help you get them, but don’t let your focus on Agile principles cause you to lose site of the goal.

Posted in Coding, Process, Project Management | Leave a Comment »

C# .Net LDAP Injection Prevention

Posted by robkraft on April 30, 2021

OWASP is a great resource for writing secure code, but some of there examples are outdated. For .Net, OWASP, as of this writing, recommends using LinqToAD (which appears to be outdated and no longer supported) or the AntiXSS tool which also appears to be outdated and a bit unreliable.

OWASP LDAP Injection Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html

A good example of how attacks on LDAP can occur via injection: https://www.synopsys.com/glossary/what-is-ldap-injection.html

In most cases, you probably just need to valid your input with a white list or a black list. White lists are always more secure than black lists, but if you are adding this check to an existing application you may prefer to start with a black list until you can identify and handle all the special characters you need to support.

Below is a bit of code I wrote to validate data against LDAP Injection risks. I found the Blacklist example here (https://stackoverflow.com/questions/53862391/how-does-ldapdistinguishednameencode-work-with-the-c-sharp-directoryservices-lib) and I added ‘|’, ‘(‘, and ‘)’ to it. Please let me know if you find an error in it!

using System.Text.RegularExpressions;
public class LDAPValidation
{
	static readonly string whitelist = @"^[a-zA-Z\-\.']*$";
	static Regex whiteListRegex = new Regex(whitelist);
	public static bool IsNameValidForLdapQueryWhiteList(string strUserName)
	{
		strUserName = strUserName.Trim();
		if (whiteListRegex.IsMatch(strUserName))
		{
			return true;
		}
		return false;
	}
	
	public static bool IsNameValidForLdapQueryBlackList(string strUserName, bool allowWildCard = false)
	{
		char[] illegalChars = { ',', '\\', '#', '+', '<', '>', ';', '"', '=', '|', '(', ')' };
		if (strUserName.IndexOfAny(illegalChars) == -1)
		{
			if (allowWildCard == false && strUserName.Contains("*"))
				return false;
			return true;
		}
		return false;
	}
	public static void RunTests()
	{
		bool result = false;
		result = IsNameValidForLdapQueryWhiteList("rkraft");
		if (result == false) throw new Exception();
		result = IsNameValidForLdapQueryWhiteList("*");
		if (result == true) throw new Exception();
		result = IsNameValidForLdapQueryWhiteList("#");
		if (result == true) throw new Exception();

		result = IsNameValidForLdapQueryBlackList("rkraft");
		if (result == false) throw new Exception();
		result = IsNameValidForLdapQueryBlackList("*");
		if (result == true) throw new Exception();
		result = IsNameValidForLdapQueryBlackList("#");
		if (result == true) throw new Exception();

	}
}

Posted in Coding, Security | Leave a Comment »

Fix Unable to Resize Microsoft Access Navigation Bar

Posted by robkraft on April 25, 2021

When you create a new Microsoft Access database from a template you may discover that you are unable to see very much of the Navigation Bar on the left. Perhaps this only happens when your monitor is a High DPI monitor such as mine. The fix is simple, simply close and re-open the Access database and the arrows to make the Navigation Bar wider should return as in this dem0: https://www.screencast.com/t/Ig5YErfhdkN8

Posted in Access, Coding | Leave a Comment »

Disable Right-Click Menus in Microsoft Access But Keep the Copy/Paste Menus

Posted by robkraft on February 26, 2021

I hope someone comments on this article to tell me that there is a better solution. I was unable to find it. The application requirements were:

  • Hide the right-click menus on the form and report title bars (shown below) to prevent users from entering “Design View”
  • Keep the right-click menus with textbox controls (shown below) to allow users to use it for Copy and Paste.

Microsoft Access has an option in the Current Database tab of Options to disable all the right-click menus and that option is called “Allow Default Shortcut Menus”. However, when I unchecked that, I could not figure out a way to enable the right-click menus solely within textbox controls to allow Copy and Paste.

My solution is to keep this option (“Allow Default Shortcut Menus”) set to checked (true), then run some code as the users open the application in AutoExec to disable the right-click on the form and report headers. I found no documentation that clearly described how to disable the right-click on the form headers, but with much trial and error I found that if I disabled all CommandBars that did not have a name, I got the result I was looking for.

Private Sub DisableCommandMenus()
    For Each Item In CommandBars
        If Item.Enabled = True Then
            'The menus we want to disable are those that don't have names
            If Trim(Item.Name) = "" Then
                Item.Enabled = False
            End If
        End If
    Next
End Sub

The code above disables menus that don’t have names. It is possible that I will need to disable more of the CommandBars, but at the moment my solution appears to be complete.

Do you know of a better solution to this?

Posted in Access, Coding | Leave a Comment »