alibek
То что основная функция вложена в оболочку — сделано специально.
Да, это заметно. Заметно, что ты специально сделал то, чего делать не надо. Видимо, сказывается отсутствие опыта. Про чистые функции ты не в курсе и про юнит-тестирование и что это вообще такое ты тоже не очень-то и знаешь. Как бы ерунды напридумывали какой-то, а ты один такой умный.
Но вот я тебе скажу так. Когда у тебя есть проект, у тебя нет времени перечитывать функции по сто раз. Особенно когда вот таких функций где-то штук сто или хотя бы десять.
Вот пример тебе.
Это твоя функция, размноженная на три функции. В каждой функции есть ошибка. Ну это подсказка тебе, потому что в реальных проектах никогда не видно, есть там ошибка или нет там ошибки. Это код полностью твой, ты сам его писал. Я ничего особого там не делал.
Теперь найти эти ошибки!
def scanfiles(base: str, ext: list = None, report: int = 100) -> list:
rec = {'level': 0, 'counter': 0, 'report': report}
def _scanfiles(base: str, ext: list = None, rec = None) -> list:
(fl, dl) = ([], [])
if rec is None:
rec = {'level': 0, 'counter': 0}
log.trace(" " * rec['level'] + "Scanning: %s", base)
for f in os.scandir(base):
if f.is_dir():
log.trace(" " * rec['level'] + "- subdir: %s", f.path)
rec['counter'] += 1
dl.append(f.path)
if f.is_file():
log.trace(" " * rec['level'] + "- file: %s", f.path)
rec['counter'] += 1
if not ext or os.path.splitext(f.name)[1].lower()[1:] in ext:
fl.append(f.path)
if rec['report'] and not rec['counter'] % rec['report']:
log.debug("Processing: %d...", rec['counter'])
for d in list(dl):
rec['level'] += 1
(f, s) = _scanfiles(d, ext, rec)
rec['level'] -= 1
dl.extend(s)
fl.extend(s)
if rec['report'] and not rec['level']:
log.debug("Processing: %d", rec['counter'])
return (fl, dl)
(fl, dl) = _scanfiles(base, ext, rec)
return fl
def scanfiles(base: str, ext: list = None, report: int = 100) -> list:
rec = {'level': 0, 'counter': 0, 'report': report}
def _scanfiles(base: str, ext: list = None, rec = None) -> list:
(fl, dl) = ([], [])
if rec is None:
rec = {'level': 0, 'counter': 0}
log.trace(" " * rec['level'] + "Scanning: %s", base)
for f in os.scandir(base):
if f.is_dir():
log.trace(" " * rec['level'] + "- subdir: %s", f.path)
rec['counter'] += 1
dl.append(f.path)
if f.is_file():
log.trace(" " * rec['level'] + "- file: %s", f.path)
rec['counter'] += 1
if not ext or os.path.splitext(f.name)[1:].lower()[1:] in ext:
fl.append(f.path)
if rec['report'] and not rec['counter'] % rec['report']:
log.debug("Processing: %d...", rec['counter'])
for d in list(dl):
rec['level'] += 1
(f, s) = _scanfiles(d, ext, rec)
rec['level'] -= 1
dl.extend(s)
fl.extend(f)
if rec['report'] and not rec['level']:
log.debug("Processing: %d", rec['counter'])
return (fl, dl)
(fl, dl) = _scanfiles(base, ext, rec)
return fl
def scanfiles(base: str, ext: list = None, report: int = 100) -> list:
rec = {'level': 0, 'counter': 0, 'report': report}
def _scanfiles(base: str, ext: list = None, rec = None) -> list:
(fl, dl) = ([], [])
if rec is None:
rec = {'level': 0, 'counter': 0}
log.trace(" " * rec['level'] + "Scanning: %s", base)
for f in os.scandir(base):
if f.is_dir():
log.trace(" " * rec['level'] + "- subdir: %s", f.path)
rec['counter'] += 1
dl.append(f.path)
if f.is_file():
log.trace(" " * rec['level'] + "- file: %s", f.path)
rec['counter'] += 1
if not ext or os.path.splitext(f.name)[1].lower()[1:] in ext:
fl.append(f.path)
if rec['report'] and not rec['counter'] % rec['report']:
log.debug("Processing: %d...", rec['counter'])
for d in list(dl):
rec['level'] += 1
(f, s) = scanfiles(d, ext, rec)
rec['level'] -= 1
dl.extend(s)
fl.extend(f)
if rec['report'] and not rec['level']:
log.debug("Processing: %d", rec['counter'])
return (fl, dl)
(fl, dl) = _scanfiles(base, ext, rec)
return fl
И тут ты начинаешь читать эту галиматью, в то время как тебе надо не читать всякую хрень уже в сотый раз, а разрабатывать дальше программу, которая сама себя не напишет.
Поэтому нужно сделать что? Нужно сделать юнит-тесты, про которые ты не знаешь.
Дальше. А что нужно тестировать этими юнит-тестами? только внешнюю функцию или только внутреннюю функции? или их обе надо тестировать? Ну в идеале их надо тестировать обе отдельно друг от друга. И как же ты протестируешь то, что вот эта внутренняя функция правильно заполняет словарь rec, а не делает в нём ошибки всякие? Для этого нужно иметь к ней доступ, и к словарю к этому тоже нужно иметь доступ, как-то его проверять.
alibek
Это красиво, когда снаружи не видно ничего постороннего
Кому не видно? Ты думаешь, это будет кто-то смотреть и читать вообще? Ты открой хоть одну реальную программу, которыми ты пользуешься каждый день, и посмотри, какой там “красивый” код у неё. Там будет говнокод на говнокоде. Ты ей можешь пользоваться годами и никогда даже не узнать, что там всякая ерунда делается внутри. А вот когда там ошибка будет, которая снаружи там сотрёт тебе полдиска или выведет тебе какую-то ложную информацию, тогда ты сразу это заметишь. А когда ты полезешь туда исправлять эту ошибку или хотя бы оценить, насколько автору программы будет её легко исправить, вот тогда качество кода и сыграет свою роль. Тогда ты по говнокоду сразу поймёшь, что это не будет исправлено никогда. Потому что автор сам же в своём говнокоде не разберётся и просто не сможет её исправить, потому что говнокод писать легко, а разгребать его потом тяжело. Поэтому то, что тяжело, он делать не будет. Он тебя просто проигнорирует, типа ошибки нет никакой или там она некритическая и так далее, и всё. Дальше ты пойдёшь программку получше искать на просторах Интернета.
Поэтому твои размышления о красивости - это туфта какая-то на уровне школоты, ничего не делавшей никогда серьёзного. Давай, напиши для ракетчиков программу красивую вот в таком своём смысле или там для врачей. И потом что-то раз и ракета летит не в космос вверх, а к тебе домой вниз, а потом тебя из дома из этого увозят в больницу и там тебе врачи делают операцию на головном мозге, а у них тоже твоя программа работает, подсказывает им что-то, которая что-то там им неправильно показывает при этом, а они даже этого не понимают. Вот это ответственность, про которую ты не в курсе.
alibek
Это красиво, когда снаружи не видно ничего постороннего и пользователя не будет возникать вопросов, что это за аргумент rec такой.
Ну ты слышал звон, но не знаешь, где он. Да, вот так вот в голом виде это правильно, но в реале по факту это неправильно. Обёртки такие, да, бывают, но это не значит, что их надо везде делать.
Вот знаешь, есть слово “каково” и есть слово “какого”. И вот люди пишут либо так, либо так всё время. А ведь это два разных слова, которые могут даже одновременно использоваться. Просто у них ума не хватает на это, они не могут этого понять, слишком узкий мозг становится барьером.
Ты знаешь,
каково это вообще, писать код в промышленных масштабах, когда у тебя каждая секунда на счету и огромная ответственность за каждую букву? Так
какого хера ты тут споришь тогда?
Вот иди и изучай свой код. Программа diff тебе не поможет, потому что этот код обычно всегда разный. А запускать каждую функцию из сотни функций ты тоже не сможешь.