Я пишу короткий модуль на Фортране 90/2003, который предоставляет простой и удобный интерфейс для подсчета времени между различными частями выполнения программы. Вдохновленный командами tic
, tac
в Matlab, идея состоит в том, что пользователь использует модуль в программе следующим образом:
program test use Timer call Tic("timername") ! some heavy stuff call Tac("timername") end program test
Теперь я знаю, как могу добиться такого результата с помощью встроенных функций Fortran. Мой вопрос заключается в том, как мне должен это сделать. Я делаю это, чтобы изучить хорошие методы проектирования, а не синтаксис Fortran.
Я определил определяемую пользователем переменную с именем Timer
, которая является основным объектом, который я использую для реализации функциональности. Однако есть (по крайней мере) два разных способа использования этого объекта, чтобы позволить пользователю использовать несколько таймеров:
а) Я могу сделать определяемую пользователем переменную Timer
общедоступной, а затем заставить пользователя создать объект таймера вручную. Пользователь должен создать столько таймеров, сколько ему нужно, а затем использовать методы для их обработки.
б) Я могу скрыть этот тип, сделав его приватным. Затем для хранения разных таймеров я создаю массив объектов Timer
в модуле как глобальную переменную, хотя и приватную для модуля, и каждый раз, когда пользователь вызывает подпрограмму Tic
, в этом массиве определяется новый таймер. В приведенном выше примере пользователь использует модуль, реализованный в соответствии со вторым подходом (обратите внимание, что программа вообще не использует ключевое слово type
).
Хотя эти два варианта технически работают (я уже реализовал оба), каждый из них имеет свои преимущества и недостатки, а известные мне правила проектирования программного обеспечения каким-то образом противоречат друг другу. Интересно, какой подход является лучшим с «ортодоксальной» точки зрения.
Вариант а) имеет то преимущество, что лучше следует ООП: пользователь явно создает объект и работает с ним. Он не использует глобальную переменную.
Вариант б) имеет то преимущество, что он более сильно «инкапсулирован». Под этим я подразумеваю, что пользователю даже не нужно знать, что такое Timer
, и даже о его существовании. Кроме того, интерфейс, предоставляемый для взаимодействия с Timer
объектами, представляет собой простую строку, что делает весь модуль более непрозрачным для пользователя, которому не нужно специально определять Timer
переменные. Он/она просто использует две подпрограммы, предоставленные модулем, которые принимают строку в качестве входных данных. Это все. Проблема в том, что у меня такое ощущение, что этот дизайн, основанный на массиве, определенном для всего модуля, противоречит правилу избегания глобальных переменных. Это не настоящая глобальная переменная, так как она частная, но все же.
Итак, имея эти два варианта, какой я должен выбрать, чтобы создать наиболее ортодоксальный подход?
PS: возможно, есть третий вариант, который позволяет пользователю создавать объекты косвенно, не имея доступа к определяемому пользователем типу (т.е. не просто определять элементы в существующем массиве, как это сделано в решении б). Я не знаю, возможно ли вообще создавать переменные во время выполнения. Любая идея в этом направлении также очень приветствуется.