javasonarqubecognitive-complexity

How can I reduce Cognitive Complexity in this block ? By the way how can this be bigger than the 15 allowed?


I have this code:

 private void processMedia(Integer mediaId, List<String> hiresPhysicalPaths) {
        final AtomicBoolean isHls = new AtomicBoolean(false);
        for (String hiresPhysicalPath : hiresPhysicalPaths) {
            REPORT.info("Process media version {} for media {} ", hiresPhysicalPath, mediaId);
            String folderName = StringUtils.substringBefore(hiresPhysicalPath, "/");
            File dir = new File(MediaRepositoryTools.getCurrentMediaPhysicalRootPath(App.getApplicationSession()), folderName);
            REPORT.info("Dir : {}", dir);
            File[] directoryListing = dir.listFiles();
            if (directoryListing == null) {
                REPORT.warn("Dir is not really a directory");
                return;
            }
            String mediaIdString = mediaId.toString();
            // loop pour savoir si le média est HLS ou pas
            for (File child : directoryListing) {
                String ext = FilenameUtils.getExtension(child.getName()).toLowerCase();
                String childFileName = FilenameUtils.getBaseName(child.getName());
                //If m3u8 file ex : 3180734-9u83wns9eh-m3u8.m3u8
                try {
                    if (isMediaHls(mediaIdString, childFileName, ext)) {
                        miseAJourFichierHLS(child);
                        REPORT.info("Le fichier m3u8 a été mis à jour pour la version : {} du média {} ", hiresPhysicalPath, mediaId);
                    } else {
                        REPORT.info("Le fichier m3u8 n'a pas été mis à jour pour la version : {} du média {} ", hiresPhysicalPath, mediaId);
                    }
                } catch (IOException e) {
                    REPORT.error("Unable to update the HLS file for media " + mediaId, e);
                }
                isHls.set(true);

                if (childFileName.startsWith(mediaIdString) && isFileNeededToBeDeleted(child.getName(), isHls.get())) {
                    this.copyOrDelete(child);
                }
            }
        }
        App.getService(TransactionService.class).withTransaction(() -> this.updatePreviewGeneratedFlagForMedia(mediaId, isHls.get()));
    }

Sonar told me to reduce the Cognitive Complexity from 16 to 15, I don't know how can it be that much since there are no nested condition in there, maybe i'm wrong.

EDIT : I edited the code in order to show you the original one with nothing missing, I'll take into account your concerns especially about the code complexity


Solution

  • I think you're thinking a little bit wrong about Cognitive Complexity.

    The general idea is the following:

    1. Ignore structures that allow multiple statements to be readably shorthanded into one
    2. Increment (add one) for each break in the linear flow of the code
    3. Increment when flow-breaking structures are nested

    So what happens in your code?
    Every declaration of a variable is +1 for the score.
    Every for loop declaration is +1.
    Every try catch and multiple catches are +1.
    You can read about it more here

    What could you do to fix this?

    Well you could check if every variable is necessary.
    You could try to get rid of the try and catch or if clauses.
    What I would do is trying to create another method for this part:


        for (File child : directoryListing) {
                String ext = FilenameUtils.getExtension(child.getName()).toLowerCase();
                String childFileName = FilenameUtils.getBaseName(child.getName());
                //If m3u8 file ex : 3180734-9u83wns9eh-m3u8.m3u8
                try {
                    if (isMediaHls(mediaIdString, childFileName, ext)) {
                        miseAJourFichierHLS(child);
                        REPORT.info(" TODO "     } else {
                        REPORT.info(" TODO  ", hiresPhysicalPath, mediaId);
                    }
                } catch (IOException e) {
                    REPORT.error("TODO " + mediaId, e);
                }
                isHls.set(true);
    
                if (childFileName.startsWith(mediaIdString) && isFileNeededToBeDeleted(child.getName(), isHls.get())) {
                    this.copyOrDelete(child);
                }
            }
    

    Also you should try to split your method in more smaller parts which you can easy understand which part does what. Your processMedia method does too much. Make it more simple and devide it. This is an approach from clean code. You can read a little bit more about it here