Category Archives: Software Construction

Topic 10 – Software Construction

Why do I need to learn about software construction?

Knowing how to write code does not mean that you know how to create real-world software. In real world, you will need to know how to manage your code, how to read the existing code, how to write code following standard styles, how to ensure that your code is working, how to automate your the process of building, testing and deploying your code, how to handle error in your applications, how to optimize your code for speed, how to write secure code, how to avoid code duplication, how to create readable code, how to create code faster. That's why you need to learn about software construction.

What can I do after finishing learning software construction?

You will know how to create software in a real world team and environment.

Hmm! Is it really useful?

If you have a doubt about its usefulness then you can delay learning it until you are tasked to create a software system and you complete a half of it and are stuck there because when you add one more feature you will get tons of bugs due to the new code. After you finish fixing 1 bug, you get 3 other bugs due to the modified code that fixes the bug.
Another scenario is that when it takes another person 6 months to read and understand the code that you wrote in 3 months in order to fix a bug or to add a new feature.

Alright! What should I do now?

Software construction requires a lot of reading. In order to get familiar with software construction you will need to read at least below books.

Please read this Steve McConnell (2004). Code Complete. Microsoft Press book first.
After that please read this Jon Loeliger and Matthew McCullough (2012). Version Control with Git: Powerful Tools and Techniques for Collaborative Software Development. O'Reilly Media book.
Alternatively, you can read  this Ben Collins-Sussman et al. (2011). Version Control with Subversion book.
After that please read this Robert C. Martin (2009). Clean Code A Handbook of Agile Software Craftsmanship. Pearson Education book.
After that please read 
- this Andy Hunt, Dave Thomas and Matt Hargett (2007). Pragmatic Unit Testing in C# with NUnit. Pragmatic Bookshelf book, and 
- this Kent Beck (2002). Test Driven Development By Example. Addison Wesley book.
After that please read 
- this Martin Fowler et al. (1999). Refactoring Improving The Design Of Existing Code. Addison Wesley book, and 
- its newer version Martin Fowler (2019). Refactoring. Improving the Design of Existing Code. 2nd Edition. Addison-Wesley Professional also.
After that please read this Elton Stoneman (2020). Learn Docker in a Month of Lunches. Manning Publications book.
If you have to work with legacy code then please read this Michael Feathers (2004). Working Effectively with Legacy Code. Prentice Hall PTR book.
After that please read this "Continuous Integration: Improving Software Quality and Reducing Risk" book. 
After that please read this "Diomidis Spinellis (2003). Code Reading: The Open Source Perspective" book.

After that please read this "Suhas Chatekar (2015). Learning NHibernate 4" book.

After that please read this "Matt Perdeck (2010). ASP.NET Site Performance Secrets" book.
After finishing the books please click Topic 11 - Software Testing to continue.

 

How to Automate Cleaning Up a .NET Solution

Motivation:

You have a .NET solution with many projects.
You need to deliver the solution to a client very frequently.
You need to clean up all intermediate folders or files to reduce the package size and make the result look tidy.
You want to automate this process to reduce cleaning up time.

Solution:
  1. In Visual Studio, right click a project and select Properties.
  2. Click on Build Events.
  3. Enter the following commands to the Post-build event command line text box:
    rd /s /q $(ProjectDir)obj
    cd $(TargetDir)
    del *.config
    del *.pdb
    del *.xml

    rd /s /q $(ProjectDir)obj: Remove the obj folder in the project directory.
    cd $(TargetDir): Move to the output directory.
    del *.config: Delete all the config files in the output directory.
    del *.pdb: Delete all the pdb files in the output directory.
    del *.xml: Delete all the xml files in the output directory.

    You can modify these commands or add new commands for your specific purpose.

  4. Save the project.
  5. Repeat the process for all the projects in the solution.

 

How to Quickly Capture and Analyze Requirements for Building a Prototype or Proof of Concept?

Motivation:

You need to quickly capture and analyze requirements for building a prototype or proof of concept for an enterprise system.

Solution:
  1. Capture any artifacts related to a business need. They may be some emails, presentation slides, a proposal document, a legacy system, some similar systems, a feature list or an initial requirement specification.
  2. Define terminologies (terms), build a background and context around the terminologies, expand the terminologies into business roles, business workflows, business components, business entities (objects), and business artifacts as much as possible.
  3. Identify the main stakeholders (roles) who will interact with the system (e.g. Guest, Admin, Developer, User, etc.) and their corresponding business problems or needs (i.e. their motivation of using the software system), and their current business workflows. Create as many scenarios (real world or domain business workflows) as possible. Create a domain model (a model of real world or domain entities, their properties and their relationships) if necessary.
  4. Identify the main components that each stakeholder will interact with (e.g. Accounts, Profiles, Reporting, APIs, Lessons, Videos, etc.) and their corresponding purposes.
  5. Identify the main tasks that each stakeholder will perform (e.g. Register an Account, Log in System, Create/Edit Profile, Create a Bucket, Generate an API Key, Create/Edit/Delete a Lesson, Create/Edit/Delete a Video, View Bandwidth, etc.).
  6. Identify the inputs and outputs and create mock-ups (sketches) or capture similar screens for each task. The quickest way to create a mock-up is to find similar existing screens in your system or external systems, and modify them. You can also search for templates of similar features in the Internet, and modify them. You can also brainstorm a  new one if you are good at creativity and imagining.
  7. Build or draw a prototype demonstrating 2 or 3 critical end-to-end workflows (An end-to-end workflow is a sequence of tasks that solves a real world problem completely). Contrast a current business workflow with a selected end-to-end workflow. The quickest way to create a prototype is to find similar existing workflow of of your system or external systems, and modify them. You can also repurpose a business workflow for a prototype. You can also brainstorm a  new one if you are good at creativity and imagining.
  8. Implement a proof of concept related to the selected end-to-end workflow.
  9. For a complicated system, you may need to implement a proof of concept, build a prototype, and create a work break down structure or product backlog in parallel to ensure that the requirements are technologically and economically feasible.

 

How to Quickly and Confidently Read Code?

Motivation:

You need to read existing source code to add your feature or fix a bug or to replicate its functions in another language or system.

Solution:
  1. Try building and running the code without any modification.
  2. Try building and running the code with your inputs.
  3. Try modifying or adding simple UI elements without touching the business logic or data layer.
  4. Try writing a unit test for a function.
  5. Try changing a variable name and make sure that the change does not break anything.
  6. Try changing a package or module name and make sure that that the change does not break anything.
  7. Try breaking a long method to smaller ones.
  8. Try breaking a large object or file to smaller ones.
  9. Try replacing an algorithm with with a better one.
  10. Try replacing an old component with a newer or better one.
  11. If you get an error when making the changes above then try showing the error on client side.
  12. If you cannot show the error on client side then try identifying the logic flow of the code related to the error, debug information, and learn about new terminologies or concepts in the code.

Example:

const maskPhone = (val) => {
    const x = val.replace(/\D+/g, '').match(/(\d{0,3})(\d{0,3})(\d{0,4})/);
    return !x[2] ? x[1] : `(${x[1]}) ${x[2]}` + (x[3] ? `-${x[3]}` : ``);
};
export { maskPhone }

If you are not sure about what the JavaScript code above does then try to learn

Another example:

<div class="container">
    <iframe class="responsive-iframe" src="https://www.youtube.com/embed/u9Dg-g7t2l4"></iframe>
</div>
.container {  
    position: relative;  
    overflow: hidden;  
    width: 100%;  
    padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */
}
/* Style the iframe to fit in the container div with full height and width */
.responsive-iframe {  
    position: absolute;  
    top: 0;  
    left: 0;  
    bottom: 0;  
    right: 0;  
    width: 100%;  
    height: 100%;
}

If you are not sure about what the HTML and CSS code above  do then try to learn

  • how many ways an element can be placed in a web page (a document),
  • what is the position relationship between an element and its parent,
  • what is the position relationship between an element and its siblings,
  • what is the position relationship between an element and the document root, and
  • what position: relative , position: absolute , overflow: hidden do.

 

 

How to Use Git

Motivation:

You want to use Git to version your files or share your files with other people.

Solution:
mkdir "D:\NETCORE"
git init
git add *.*
git commit -m "add initial files"
git remote add origin https://github.com/huybien/asp.net-core.git
git push -u origin master
  • Push changes to a remote repository.
git add .
git commit -m "CP form"
git push -u origin master
  • Update (fetch and merge) a local repository.
git pull
  • Force updating (fetch and overwrite) the current repository.
git fetch --all
git reset --hard origin/master
git clean -fd
git pull
  • Force updating (fetch and overwrite) a local repository (e.g. C:\Users\admin\Downloads\code).
git -C C:\Users\admin\Downloads\code fetch --all
git -C C:\Users\admin\Downloads\code reset --hard origin/master
git -C C:\Users\admin\Downloads\code clean -fd
git -C C:\Users\admin\Downloads\code pull
  • Pull (checkout) a remote repository (e.g. https://github.com/huybien/asp.net-core.git) to an empty local folder (e.g. C:\Users\admin\Downloads\code).
cd C:\Users\admin\Downloads\code
git init
git remote add origin -f https://github.com/huybien/asp.net-core.git
git pull origin master
or
git pull origin main
  • Reset (Revert) a local repository to a previous version.
cd C:\Users\admin\Downloads\code
git log --oneline
git reset --hard 4355842
where 4355842 is a version id.

How to Quickly and Reliably Fix a Bug

Problem:

It may take you much effort to fix a bug. The fix may not be reliable. How can you avoid this situation?

Solution:
  1. Try to reliably reproduce the bug. It is okay if this may not be successful.
  2. Try isolating the bug on the same environment by using specific, smaller data and settings. It is okay if this is still not successful.
  3. Search for an existing solution using the error message, the library or framework name and version, and the operating system name and version. This can save us a lot of effort.
  4. Try to understand all the concepts in the error message.
  5. Debug and log messages to identify the exact location of the source code that causes the issue. In order to to this we need to do the followings.
    • Identifying the flow of the data, i.e. the use case, the entry point and the exit point.
    • Trying to understand the programming language syntax. Do not guess anything.
    • Trying to understand the purpose, inputs and outputs of a library function. Again, do not guess anything.
    • Trying to understand the data structure and a part of the database schema related to the use case.
    • Trying to review some values inside the database if possible.
    • Trying to understand the concepts, algorithms and architecture related to the use case.
    • These steps may be done in parallel and iteratively.
  6. Guess a cause of the problem based on the information retrieved in the third step.
  7. Try to isolate the issue, i.e. try to reproduce the issue using specific code and unit tests, if possible.
  8. Search for or propose a solution for the cause, i.e. propose a fix.
  9. Test the fix.
  10. Repeat from Step 5 to 8 if needed.