Testing: Eastern Philosophy and Testing can go Hand in Hand

During the preparation for a talk about practical testing and test coverage analysis I found in the large web a small booklet “The Way of Testivus” (http://www.agitar.com/downloads/TheWayOfTestivus.pdf). This small booklet is a humorous summary of testing principles and wisdom packaged into a nice form for everybody to read who is interesting in testing to get inspired and to have a fun time.

This book clearly shows, that testing is not a matter of good or bad or right and wrong, it is about thinking of the right way. There is not standard recipe to use to write good tests, enough tests or what so ever.

For my talk mentioned above, I found an additional post (at www.artima.com/forums/flat.jsp?forum=106&thread=204677) with a nice story written in the same style:

Testivus On Test Coverage

Early one morning, a programmer asked the great master:

“I am ready to write some unit tests. What code coverage should I aim for?”The great master replied:

“Don’t worry about coverage, just write some good tests.”The programmer smiled, bowed, and left.

Later that day, a second programmer asked the same question.

The great master pointed at a pot of boiling water and said:

“How many grains of rice should put in that pot?”The programmer, looking puzzled, replied:

“How can I possibly tell you? It depends on how many people you need to feed, how hungry they are, what other food you are serving, how much rice you have available, and so on.”“Exactly,” said the great master.

The second programmer smiled, bowed, and left.

Toward the end of the day, a third programmer came and asked the same question about code coverage.

“Eighty percent and no less!” Replied the master in a stern voice, pounding his fist on the table.The third programmer smiled, bowed, and left.

After this last reply, a young apprentice approached the great master:

“Great master, today I overheard you answer the same question about code coverage with three different answers. Why?”The great master stood up from his chair:

“Come get some fresh tea with me and let’s talk about it.”After they filled their cups with smoking hot green tea, the great master began to answer:

“The first programmer is new and just getting started with testing. Right now he has a lot of code and no tests. He has a long way to go; focusing on code coverage at this time would be depressing and quite useless. He’s better off just getting used to writing and running some tests. He can worry about coverage later.”

“The second programmer, on the other hand, is quite experience both at programming and testing. When I replied by asking her how many grains of rice I should put in a pot, I helped her realize that the amount of testing necessary depends on a number of factors, and she knows those factors better than I do – it’s her code after all. There is no single, simple, answer, and she’s smart enough to handle the truth and work with that.”

“I see,” said the young apprentice, “but if there is no single simple answer, then why did you answer the third programmer ‘Eighty percent and no less’?”

The great master laughed so hard and loud that his belly, evidence that he drank more than just green tea, flopped up and down.

“The third programmer wants only simple answers – even when there are no simple answers … and then does not follow them anyway.”The young apprentice and the grizzled great master finished drinking their tea in contemplative silence.

My experience is, that the test coverage percentages are totally meaningless. The numbers do not tell anything meaningful at all, it is only a rough number on how much testing is done, but nothing about the test quality. The only really interesting information are the lines of code which are not tested at all. For these lines, one should think about adding some meaningful tests or about removing the code, because it is not used at all like dead code.

 

JUnit test reporting

Some time ago in 2011, I asked a question in stackoverflow about test report enrichment of JUnit tests. Because I was asked several times on this topic afterwards, and today again, I write down  the solution Ideveloped and used that time. Currently, I do not have a better idea, yet.

The issue to solve

For a customer detailed test reports are needed for integration tests which not only show, that everything is pass, but also what the test did and to which requirement it is linked to. These reports should be created automatically to avoid repetitive tasks to save money and to not frustrate valuable developers and engineers.

For that, I thought about a way how to document the more complex integration tests (which is also valuable for component tests). A documentation would be needed for classes and test methods. For the colleagues responsible for QA it is a good help to see to which requirement, Jira ticket or whatever the test is linked to and what the test actually tries to do to double check it. If the report is good enough, it may also be sent out to the customers to prove quality.

The big question now is: How can the documentation for each method and each test class put into the JUnit reports? JUnit 4.9 was used at the beginning of this issue with Maven 3.0 and not I am on JUnit 4.11 and Maven 3.1.0.

The solution

I did what was suggested in stackoverflow, because I did not find a way to enhance the surefire reports directly. The solution for me was the development of a JUnit run listener which collects some additional information about the tests which can be later used to aggregate the reports.

The JUnit listener was attached to maven-surefire-plugin  like:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.12</version>
    <configuration>
        <properties>
            <property>
                <name>listener</name>
                <value>fully.qualified.class.name.to.your.listener</value>
            </property>
        </properties>
    </configuration>
</plugin>
The listener needs to extend org.junit.runner.notification.RunListener and there you can overwrite the methods testRunStarted, testRunFinished and so forth. The listener needs to be put into a separate Maven project, because a listener cannot be build and used in the same project, so another project is to be created separately.
For the tests itself, I also created an annotation where I put it in the requirements id and other information needed:
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface TestDoc {
    public String testId();
    public String rationale();
    public String bugId() default "";
    /* Put in what you need... */
}
A test class can then look like that:
@TestDoc(testId="123", rationale="Assure handling of invalid data does not cause a crash.", bugId="#42")
public class InvalidStreamingTests {

    @Test
    @TestDoc(testId="124", rationale="Check for stream which aborts and leads to incomplete content.")
    public void testStreamAbort()
    {
        /* The actual test code */
    }
}
In the run listener one gets the reference to the actual test which can be scanned for annotations via reflection.The Description class is quite handy, one can retrieve the test class as easy as:
String testClassName = description.getClassName();
The information found there can be stored away, what I did in a simple CSV file. After the tests run, these information can be gathered into a fancy report. The information which can be collection reaches from start timestampes, over the actual test class calls, the result of the tests (assertions and assumptions) to the finish time stamps. The classes can be check via reflection at all times and all information can be written into a file or even to a database or server.
The reporting was done offline later on, when I first used this solution. But, if some more work effort is possible, a Maven report plugin (or a normal plugin) can be written which collects the information in the post-integration-test phase for example. Here the limitation is the imagination only. It depends whether only a technical report is needed as TXT file or a fancy marketing campaign needs to be build around it. In daily life it is something in between.

Sample Defect Cost Calculations: Why tests are worth it…

Sample Defect Cost Calculation

The cost calculation is not very simple and a lot of assumptions, and estimations are needed. The following definitions, terms, and formulas are a first step for an understanding of the costs related to defects and testing. Especially, the results shall be an example and maybe an argument for a strong and tight testing.

Let us define first the Defect Detection Percentage (DDP):

DDP [$] =  (bugs detected) / (bugs present) = (test bugs) / (test bugs + production bugs)

The defect detection percentage is a quite simple formula, because it is just the ratio of the bugs found before delivery to the total bugs in the code which is unknown. The real insight comes, as soon as the ratio is rewritten to the ratio of the bugs found during testing and the sum of the found bugs and the bugs which are delivered into production. This formula shows in a very simple manner the simple truth: All bugs which are not found during test go directly into production. The first ratio is to abstract to get this point straight with the right emphasis, but that is really important: Bugs in production at customer’s site destroy reputation, decrease future revenue due to lost customers, and in worst case bring in calls for liability.

The relationship of total found bugs to critical bugs found should be under all circumstances:

DDP (all bugs) < DDP(critical bugs)

Or in other words: It should be the final goal to have a much better detection percentage for critical bugs than for all bugs or minor bugs. It is in most cases not very critical to have a button in a UI at the wrong position, but a crashing application or an application which cannot keep a database connection open, is critical.

The consequence is: We should put more time and effort into testing of critical and blocking defects than on minor issue testing. I have seen this in real world already. The focus and the effort on the UI was remarkable, because it was obvious and everybody could see it (especially the own management and the customers management), but the performance was not sufficient and the stability was not as good as needed. But, the product was shiny and looked beautiful…

Have a look into the post about the quality characteristics: https://rickrainerludwig.wordpress.com/2014/02/10/software-quality-charateristics-in-iso-9126. What is critical and what not may change from project to project. A deep though is needed for the weighting, but the weighting should lead the testing priorities.

The possible costs for defects (see Beautiful Testing: http://astore.amazon.de/pureso-21/detail/B002TWIVOY) can be classified as:

  1. Cost of detection: All costs for testing and accompanying actions. Even if no bugs are found, there are costs which need to be taken into account. For example: Performing a quality risk analysis, setting up the test environment, and creating test data are activities to be taken into account. They all incur the costs of detection and there are much more tasks to do. These are the permanent costs on timely basis.
  2. Cost of internal failure: The testing and development costs which incur purely because bugs are found. For example filing bug reports, adding new tests for the found bugs, fixing bugs, confirmation test bug fixes, and regression testing are activities that incur costs of internal failure. These are the actual costs per bug.
  3. Cost of external failure: The support, testing, development, and other costs that incur because no 100% bug-free software was delivered. For example, costs for technical support, help desk organization, and sustaining engineering teams are costs of external failure. These costs are much higher. The costs are at least as high as the internal failure costs, but there are additional costs for external communication, containment, and external support.

Let’s define the Average Cost of Test Bug with the knowledge from above:

ACTB = (cost of detection + cost of internal failure) / (test bugs) [$/Bug]

There is also the definition of the Average Cost of a Production Bug:

ACPB = (cost of external failure) / (production bugs) [$/Bug]

With both definitions from above the calculating of a Test Return On Investment can be defined:

TestROI = ( ( ACPB – ACTB) x test bugs) / (cost of detection) [1]

Example Test ROI Calculation

Let us assume, we have 5 developers in a test team which cost about 50k$ per month (salary and all other costs). Let us further assume, they find an average of 50 bugs per month and a customer finds 5 bugs a month. The production bug cost is assumed with 5k$ (5 people for a week for customer support, bug fixing and negotiations) and a testing bug cost of 1k$ (1 developer for a week). We have the following numbers:

ACTB = (50 k$/month + 50 bug/month * 1k$/bug) / (50 bug/month) = (100 k$/month) / (50 bug/month) = 2k$/bug

ACPT = (10 bug/month * 5 k$/bug) / (10 bug/month) = 5 k$/bug (what we obviously defined)

TestROI = ((5 k$/bug – 2k$/bug) * 50 bug/month) / (50 k$/month) = 3

This simple example shows, that testing might be economically meaningful…

Automated and Manual Regression Tests

Some simple formulas for automated testing. It is sometimes difficult to communicate the positive impact of automated testing, because the initial costs for hardware, operational costs and the costs for development of automated tests are significant. But, the next formulas give an impression for the benefit.

Let us define the Regression Test Automation ratio:

RTA = (automated regression tests) / (manual tests + automated regression tests)

The Regression Risk Coverage is shown here to have the complete set of formulas:

RRC = (regression risk covered) / (regression risks identified)

The RRC is used as a measurement for the confidence on the automated tests. The higher the RRC, the better the confidence not to deliver critical bugs.

To calculate the benefit of automated test, the Acceleration of Regression Testing can be used:

ART = (manual regression test duration – automated regression test duration) / (manual regression test duration)

Automated tests bring benefits twofold:

  1. Development and test engineers are relieved from repetitive work. Engineers in most cases are not very good in this. Engineers are better placed inside of development projects and in failure analysis which brings more economical benefits. Every hour saved for manual testing can be better spend in functionality development or quality improvement.
  2. Automated tests can be run anytime, even during night. Continuous Integration (CI) and Continuous Delivery (CD) approaches use this by automated triggering of tests. Tests are run for example after each code change in the Source Code Management tool. Bugs can be found and fixed very quickly.

The costs can be lower, too. If the testing environment costs 1k$/month, it is about 1/5 of a developer, but it runs 24/7 and executes much more tests per time unit than any developer can do. It is a real bargain.

Summary

Even it is only a short post on some defect cost calculations, it shows that testing is meaningful economically. The costs for testing like developers developing automated tests, dedicated testers doing manual tests, hardware, QA staff managing testing and assuring the quality compliance, and so forth seem very high, but taken into account that the costs for defects increase significantly the later they are found in the product life cycle, testing brings a huge benefit.

Continuous Improvement in Software Development

I already wrote about “The Killer Difference between Mechanical Engineering and Software Engineering” and “Similarities in Quality Assurance between Cambodian Silk Painting and Software Development”. Related to this some comments on continuous improvement in software development and refactoring.

As mentioned earlier, there is not classical production process in software development. In classic production, we have repetitive work and quality measures like Cp and Cpk which are monitored over time and if they are out of certain limits (warn limits and out of specification limits), actions are taken. Over time this leads to a better production process by continuous monitoring and continuous improvement by taking the metrics from the monitoring process. In software development we need to do something else. We need a new approach (see post about the difference on mechanical engineering and software engineering).

During software development we need to use raw models to guide the development like source conventions, design patterns, and standard designs for error handling and such stuff. A clean, layered architecture also helps to guide development and leads to good code on green field projects (see the article about QA for silk painting).  But, as soon as the already present code is changed, the code degrades slowly, but steadily. Here a totally new approach needs to come in: We need to improve the existing code as steadily as the code degrades. As the entropy in physics tells us: The entropy is increasing steadily as long as there is no energy used to decrease it. That is why we need to put a lot of effort into the permanent improvement of existing code.

The buzz word for this process is “Refactoring”. It is needed to have a fixed amount of time planned for continuous improvement of existing code by refactoring. I suggest an amount of 5% to 10% of time as a minimum for each project. Depending on the actual state of the project it may be needed to plan more. Up to 50% is realistic if a new brown field project is  started (a new development is started on existing code) to smooth the way for the new project. There are some points to consider:

  1. Is the refactoring done independently? Are some people planned to do only refactoring on the code independently of the other developers? This can be done to change the architecture or some designs. Exchanging frameworks, cleaning up parts of the software or separating some parts from another are tasks which can be considered to be done, too.
  2. Is the refactoring done during development? The refactoring can be done during the development of new functionality. This approach needs a strong mindset of the developers. For each new functionality to be implemented, the code is evaluated first and refactored to provide a clean ground for the new functionality. It is better to clean the effected parts first, before adding new functionality.

Both approaches have their advantages and disadvantages. I suggest to do both: It is best to train developers to do some refactoring before new functionality is implemented to get a clean implementation of new functionality. These refactorings are allowed to be made after it was clarified that enough tests back up the changes. If there are not enough: These tests need to be created. In the daily standup each developer needs can tell her colleagues which parts are to be refactored to avoid conflicts due to simultaneous code changes. Additionally, a senior developer or architect may be needed to be asked for approval if the changes are more risky or effect too much code.

Independent refactorings should be added as tasks to the backlog as soon as they touch the overall design or architecture. These refactorings should be planned separately, but it is to be assured, that they are not forgotten. A good backlog is needed for that and a good set of rules on how to determine the priorities for each ticket.

Can Programs Be Made Faster?

Short answer: No. But, more efficient.

A happy new year to all of you! This is the first post in 2014 and it is a (not so) short post about a topic which follows me all the time during discussions about high performance computing. During discussions and in projects I get asked about how programs can be programmed to run faster. The problem is, that this mind set is misleading. It always takes me some minutes to explain the correct mind set: Programs cannot run faster, but more efficient to save time.

If we neglect that we can scale vertically by using faster CPUs, faster memory and faster disks, the speed of a computer is constant (by also neglecting CPUs which change there speed so save power). All programs run always with the same speed and we cannot do anything to speed them up by just changing the programming. What we can do is, to use the hardware we got as efficient as possible. The effect is: We get more done in less time. This reduces the program run time and the software seem to run faster. That is what people mean, but looking on efficiency brings the mind set to find the correct leverages on how to decrease run time.

A soon as a program returns the correct results it is effective, but there is also the efficiency which is to be looked at. Have a look to my post about effectiveness and efficiency for more details about the difference between effectiveness and efficiency. To gain efficiency, we can do the following:

Use all hardware available

All cores of a multi-core CPU can be utilized and all CPUs of the system if we have more than one CPU in the system. GPU or physical accelerator cards can be used for calculation if present.

Especially in brown field projects, where the original code comes from single core systems (before 2005 or so) or system which did not have appropriate GPUs (before 2009), developers did not pay attention multi-threaded, heterogeneous programming. These programs have a lot of potential for performance gains.

Look out for:

CPU utilization

Introduce mutli-thread programming into your software. Check the CPU utilization during an actual run and look for CPU idle tines. If there are any, check your software whether it can do something at the time the idle times occur.

GPU utilization

Introduce OpenCL or CUDA into your software to utilize the GPU board or physics accelerator cards if present. Check the utilization of the cards during calculation and look for optimizations.

Data partitioning for optimal hardware utilization

If a calculation does not need too much data, everything should be loaded into memory to have the data present there for efficient access. Data can also organized to have access in different modes for sake of efficiency. But, if there are calculations with amounts of data which do not fit into memory, a good strategy is needed for not to perform calculations on disk.

The data should be partitioned into smaller pieces. These pieces should fit into memory and the calculations on these pieces should run in memory completely. The bandwidth CPU to memory is about 100 to 1000 faster than CPU to disk. If you have done this, check with tools for cache misses and check whether you can optimize this.

Intelligent, parallel data loading

The bottle neck for calculations are CPU and/or GPU. They need to be utilized, because only they bring relevant results. All other hardware a facilities around that. So, do everything to keep the CPUs and/or GPUs busy. It is not a good idea to load all data into memory (and let CPU/GPU idle), then start a calcuation (everything is busy) to store the results afterwards (and have the CPU/GPU idle again). Develop you software with dynamic data loading. During the time calculations run, new data can be caught from disk to prepare the next calculations. The next calculations can run during the time the former results are written onto disk.This maybe keeps a CPU core busy with IO, but the other cores do meaningful work and the overall utilization increases.

Do not do unnecessary things

Have a look to my post about the seven muda to get an impression about wastes. All these wastes can be found in software and these lead into inefficiency. Everything which does not directly contribute to the expected results of the software needs to be questioned. Everything which uses CPU power, memory bandwidth and disk bandwidth, but is not directly connected to the requested calculation may be treated as potential waste.

To have a starter look for, check and optimize:

Decide early

Decide early, when to abort loops, what calculations to do and how to proceed. Some decisions are made in code on a certain position, but sometimes these checks can be done earlier in code or before loops, because the information is already present. This is something to be checked. During refactorings there might be other, more efficient positions for these checks. Look out for them.

Validate economically

Do not check in functions the validity of your parameters. Check the model parameters at the beginning of the calculations. Do it once and thoroughly. If these checks are sufficient, there should be no illegal state afterwards related to the input data. So they do not need to be checked permanently.

Let it crash

Check only input parameters of functions or methods if a fail of those be fatal (like returning wrong results). Let there be a NullPointerException, IllegalArgumentException and what so ever if something happens. This is OK and exceptions are meant for situations like that. The calculation can be aborted that way and the exception can be caught in a higher function to abort the software or the calculation gracefully, but the cost to check everything permanently is high. On the other side: What will you do when a negative value come into a square root function with double output or the matrix dimensions do not fit in a matrix multiplication? There is no meaningful way to proceed, but to abort the calculation. Check the input model and everything is fine.

Crash early

Include sanity checks in your calculations. As soon as the calculation is not bringing more precision, runs into a wrong result, gives the first nan or inf values or behaves strangely in any way, abort the calculation and let the computer compute something more meaningful. It is a total waste of resources to let a program run, which does not do anything meaningful anymore. It is also very social to let other people calculate stuff in the meantime.

Organize data for efficient access

I have seen software which looks up data in arrays element wise by scanning from the first element to the position where the data is found. This leads into linear time behavior O(n) for the search. This can be done with binary search for instance which brings logarithmic time behavior O(log(n)). Sometimes, it is also possible to hold data in memory in a not normalized way to have access to it in different ways. Sometimes a mapping is needed from index to data and sometimes the other way around. If memory is not an issue, think about keeping the data in memory twice for optimized access.

Conclusion

I hope, I could show how the focus on efficiency can bring the right insights on how to reduce software run times. The correct mind set helps to identify the weak points in software and the selection of the points above should point out some directions to look into software to find inefficiencies. A starting point is presented, but the way to go is different for every project.

Software Quality Charateristics in ISO 9126

In ISO 9126 software quality characteristics are defined which are used to evaluate the quality of a software product. These characteristics shall assure a complete evaluation, but in most projects these characteristics need to be weighted to each other. This evaluation procedure is quite complex and it differs from project to project and maybe also over time due to changing requirements (Agility). I want to give here a starting point for the discussion which is true in most projects, but need to be refined.

The Characteristics

The main software characteristics in accordance to ISO 9126 are:softwarequality-en

  1. Functionality
  2. Reliability
  3. Efficiency
  4. Usability
  5. Maintainability
  6. Portabilty

A graphical representation of this main characteristics and the sub-characteristics is show nearby. I already ordered them in correspondence to the importance for most software projects. But, this is only half of the truth. In the following sections the explanations are provided.

Functionality

Security is divided into the following sub-characteristics:

  1. Suitability
  2. Accuracy
  3. Interoperability
  4. Security
  5. Functional Compliance

This is the most crucial point for customers. With incorrect results, unsuitable models and software which can not inter-operate with their environments, our software is useless. A software which has not the functionality needed, is never accepted by customers.

Reliability

The sub-characteristics are:

  1. Maturiy
  2. Fault Tolerance
  3. Recoverability
  4. Reliability Compliance

Reliability is the second most important point in software development. As soon as the software has a certain functionality, this functionality needs to be available. This is needed to generate a constant revenue, to provide services to end user for their satisfaction or to monitor safety critical operations. A weak reliability will lead to loss of revenue, loss of customers and in critical area to injuries and deaths.

Efficiency

Sub-characteristics are:

  1. Time Behavior
  2. Resource Utilization
  3. Efficiency Compliance

Our customers have fabs where they try to increase the throughput on daily basis. Our software needs to be performant, too. We should pay some attention to performance and resource usage. But, this must no be on cost of maintainability. Ask your senior about the right decisions if unsure.

Usability

The sub-characteristics are:

  1. Understandability
  2. Learnability
  3. Operability
  4. Attractiveness
  5. Usability Compliance

Our customers and clients want software which is self-explanatory and easy to use. We should keep in mind to keep our customers happy with nice and usable GUIs, too.

Maintainability

Maintainability’s sub-characteristics are:

  1. Analyzability
  2. Changeability
  3. Stability
  4. Testability
  5. Maintainability Compliance

This is the most important point for ourself! Code which is not maintainable leads to code which can not be changed, can not be kept stable and secure and may lead into a product which can not be sold. On the other side, we can make our lifes much easier with easy to read and easy to write code.

Portability

The sub-characteristics for Portability are:

  1. Adaptability
  2. Installability
  3. Co-Existence
  4. Replaceability
  5. Portability Compliance

This point is of minor importance, but should be kept in mind by architects. The system itself and technologies used within our products are meant to change in future. We should build systems in a way, that sub-systems may be changed without too much work.

Sum Up

As I wrote before, the statements I made above will be true for most software products, but there are always differences from one project to another. The ordering above will lead into good software which is also sell-able, but it is kind of focused to technical

Let’s have a short look to Video Games: As far as I observe the market, the priorities are different here. Performance in Video and Realism (Efficiency) are one of the highest values and Reliability comes behind. In forums people talk about awesome graphics and realism, but they complain about stability issues within new products, but the products are bought nevertheless. It is the graphics which is valued most. Sometimes the functionality also is behind Efficiency. There are some video games out there with a very thin story, which are not intuitive to use, but which are bought for the cheer graphics and their open world.

Another example is software for end users: Here the Usability is ranked in most cases above Efficiency. End user need to have a good time using the software. Easy usage is much more important for them then waiting for some seconds for an operation to finish. The famous flying object which show activity, nice graphics and so forth are more important than efficiency. Have a look to one of the famous smart phone manufactures: There OS looks great, is easy to use and is stable. The functionality is not overwhelming, but it is stable and fast enough. The priorities are set right, but different then I wrote above.

5S Methodology and Software Development

The 5s methodology is used to keep the working environment clean, ordered and efficient. I came across this methodology when I was working in a production area for a semiconductor factory. This system was referenced from time to time when internal audits showed some weaknesses in regard to efficiency, order or cleanness. For a short reference on 5s methodology have a look to: http://en.wikipedia.org/wiki/5S_%28methodology%29.

The key topics Sorting, Straightening, Shine, Standardize, and Sustain are quite weak translations of the Japanese words Seiri, Seiton, Seiso, Seiketsu, and Shitsuke due to the wish to translate it into English words which also start with the S letter. Nevertheless, they express roughly the idea behind that and details are explained below. Again like for the post about the Seven Muda, I also translate these topics into the field of Software Engineering as I understand it.

Sorting (Seiri)

This principle has a strong relation to the Muda Inventory, Over-Processing and Over-Production.

Classic meaning:

The meaning here is: Remove everything unnecessary. Check all tools, materials, and machinery and remove everything which is not needed. This cleans out the workspace, makes spaces and removes distraction. The rate of defects decreases due to a lowered risk to use wrong tools or materials and more space means less incidents.

Software Engineering:

For software engineering it is the same, but it is twofold:

  1. For development process: Remove all tools and stuff in your workspace, IDE or PC which is not needed. These tools distract the developer, make the workspace cleaner as mentioned above and also sometimes more stable (everyone who uses Eclipse with a lot of plugins know, what I mean).
  2. For Architecture and Design: Remove all components, interfaces, libraries, and systems which are not needed. These are added as soon as they are needed. For example: To implement everything in patterns right from the beginning does not make much sense, when  not needed, yet. The requirements may change and what was though at the beginning is needed, will not be needed further on. Only use and implement, what is needed and postpone everything else into the future when needed.

Not hitting the correct meaning, but also part of it is duplicate code. Duplicate code is something which is redundant. Redundancy is also something which needs to be cleaned out. Duplicate code is a nightmare for maintainability and should be avoided in all means.

Straightening (Seiton)

This principle has a relationship to Muda Transport, Motion and Waiting.

Classic meaning:

This principle is about straightening the processes. Everything should be processed in an efficient way. Transport ways need to be shortened, motions to be avoided, unnecessary tasks to be eliminated and wait time to be reduced. This principle can only be applied in iterations with close observations.

Software Engineering:

In software engineering this principle can be used as a driving factor for lean architecture and design. The Muda Transport, Motion and Waiting in post about the Seven Muda give hints were to look out in software engineering.

Shine (Seiso)

Classic meaning:

This is about cleaning and ordering the workspace. As soon as everything is clean and ordered, the station is ready for usage. In each shift or on daily basis, cleaning and ordering should be scheduled. On such a workspace, process flaws and defects are better to find and the work is easier, cleaner and safer.

Software Engineering:

For software engineering, I would refer to Clean Code and Refactoring. Write clean code and clean the code as soon as bad smells are detected. This keeps the code clean and erosion is prevented. Bugs are easier to spot in clean code and also easier fixed.

With refactoring the architecture and design stays clean, too. This assures an understandable architecture which support bug fixing and improvements.

These actions should take place during normal work, but also scheduled at the end of sprints for instance. Code Reviews can also set in place in critical parts of the software to assure the right measure of quality. A time budget from 5% to 50% depending of the state of the code should be scheduled. In brown field projects with a lot of legacy code massive cleanup can help to improve the later development of new functionality dramatically. But, also in green field projects erosion takes place and should be fought with a 5% time budget at least. Have a look to the books Refactoring by Martin Fowler and Clean Code by Robert C. Martin for details, or Working Effectively with Legacy Code by Robert C. Martin.

Standardize (Seiketsu)

Classic meaning:

In fabrications all work stations should be standardized, what means that they should look, function and feel all the same. It is more easy to train people on a new station that way, the quality is higher due to a lower defect rate and it is also cheaper if it is possible to reuse procedures, tools and material.

Software Engineering:

For software engineering, there are two possible meanings:

  1. All developers should use the same tools for development. It is more easy then to maintain a development environment where only one IDE is present, one build system, on OS and so forth. Only for testing there may be some variation, but for pure development, it is easier to deal with one kind of tool for one purpose.
  2. Within the software everything should be handled in a standardized way. So the architecture should define standards and also design. For instance it could be a standard that all components of a larger system communicate to each other with a REST interface. There only one REST library is used. It would be worse if all components would talk with another protocol like SOAP, RMI, EJB and so forth. For design it is the same. Exception handling for instance should be defined how it should be done. How are files handled? Coding guide lines and so forth.

Standards help that people can identify parts in larger systems more easily. Understandability and Maintainability improve dramatically.

Sustain (Shitsuke)

The first four points are hard enough to accomplish, but this sustaining point is even harder. What you did and accomplish in the first four sections is a large step to an efficient production environment. This is something which is done in form of a project, but a project is time limited. The real art of 5S is now to keep the state what was accomplished and to even improve it. That’s a huge leap! The goal is to establish a control system which checks for instance from time to time the current situation in a kind of internal audit and to raise the issues found. The issues should be fixed as soon as possible. With a regular check of the other 4S and an improvement of the findings, the current state can be sustained and even improved. But, this needs a lot of attention and energy.

In Software Engineering the buzz words Code Smell (or just Smell), Refactoring and Architecture Refactoring come to mind. As soon as there are bad smells, an action needs to be taken to fix this issue. The longer the issues is present, the more it manifests itself and the harder is it to be fixed. As the Asian proverb says: It is easy to change the direction of a river at its source…

Further Enhancements

Sometimes some enhancements are added. These points express some enhancements which should be taken care of, too. I only explain them shortly, because they are quite self explanatory.

Enhancement to 6S: ‘Get Used to it’ (Shukan)

This point is often added to the original 5S. With the checks and fixes in the Sustaining part, people get trained to keep an open eye on 5S. Over time everybody should develop a habit of fixing everything which is not in order to have an easier and more efficient life. It is good to create a company culture for 5S.

Safety

Classic meaning:

This is very easy: Keep everything and order and additionally, watch out for sources of accidents and prepare everything that this accidents cannot happen.

Software Engineering:

Here it is about the quality of source code and architecture for accidents like crashes, wrong results, stability and so forth.

Security

Classic meaning:

Keep people out which are not supposed to be in certain area. Keep secrets secret and confidential data confidential.

Software Engineering:

Build  your software in a way that only authenticated people are allowed to change settings which they are authorized to and keep data protected from people which are not allowed to see them.

%d bloggers like this: