3

I'm writing a function that needs to get libraries (files) for a Company from a folder path. Thereafter it needs to install those in a repository. While doing this I need to inform the user what is happening. Below is the code.

    def run(self):
        self.__get_libraries(self.__companies)
        for company in self.__companies:
            self.__install_libraries(company)

        return True, ""

    def __get_libraries(self, companies):
        output.printnlog("Searching library files for:")

        total_libraries = 0
        for company in companies:
            output.printnlog("- {} in {}".format(company.name, company.libraries_folder_path))
            company.get_library_files()
            total_libraries += len(company.get_library_files())

        output.printnlog("Libraries found:", pre_empty=True)
        output.printnlog("- All companies: {}".format(total_libraries))
        reporter.setelement(self.__xml_total_libraries, total_libraries)
        for company in companies:
            output.printnlog("- {}: {}".format(company.name, len(company.get_library_files())))
            reporter.setelement(company.xml_element, company.get_dict())

    def __install_libraries(self, company):
        output.printnlog("Installing library files for {} from {}."
                         .format(company.name, company.libraries_folder_path), pre_empty=True)

        repository = librarymanager.repositories[0]
        libraries = company.get_library_files()
        width = int(math.ceil(math.log10(len(libraries))))
        index = 1
        for library in libraries:
            output.printnlog("Installing library {} of {}: {}"
                             .format(str(index).rjust(width), len(libraries),
                                     os.path.basename(library)))
            install_start_time = datetime.now()

            librarymanager.install_library(library, repository, True)

            elapsed_time = output.log_elapsedtime("Library {} of {} installed within {}."
                                                  .format(str(index).rjust(width), len(libraries),
                                                          "{}"), install_start_time)
            reporter.setelement(company.xml_element.elrecords, {
                "record": {"nr": index, "library": os.path.basename(library),
                           "elapsed_time": elapsed_time}})

            index += 1

Now, everything is working fine but I have the feeling that the code that is actually doing something is lost by the code to inform the user. If I'd stip all the informative stuff, I end up with only this:

    def run(self):
        self.__get_libraries(self.__companies)
        for company in self.__companies:
            self.__install_libraries(company)

        return True, ""

    def __get_libraries(self, companies):
        for company in companies:
            company.get_library_files()

    def __install_libraries(self, company):
        repository = librarymanager.repositories[0]
        libraries = company.get_library_files()
        for library in libraries:
            librarymanager.install_library(library, repository, True)

Is there a good compromise to make between both versions of code? I need the information stuff as a requirement but is it possible to "hide" it from the actual execution code?

1
  • Have you considered following the traditional Unix approach to only tell the user about things that are going wrong? If a utility works as desired, there should be no output at all (unless of course the purpose of the utility is to output something). Oct 8, 2021 at 11:59

1 Answer 1

5

I'm very much a beginner with Python, so the following syntax is likely nonsense, but hopefully it demonstrates my point.

Focusing on __install_libraries by way of example, I'd have another class, module or whatever that handled the messaging and would anticipate ending up with compromise code something like:

def __install_libraries(self, company):
    user_notifier = new UserNotifier(company)

    user_notifier.notify_installing_libraries()

    repository = librarymanager.repositories[0]
    libraries = company.get_library_files()

    for library in libraries:
        user_notifier.notify_installing_library(library)
        librarymanager.install_library(library, repository, True)
        user_notifier.notify_installed_library(library)

Then all the code that calculates width, is used to format the messages and increments index gets moved into the UserNotifier module/class.

Your code then focuses on installing the libraries and delegates reporting to another separate piece of code, which is what I generally see as the best compromise in these situations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.