Exercise 3: A Seventh Method the Classifier Doesn't Recognize — Possible Solution ==================================================================== THE NEW METHOD ------------------------------ def log_login_attempt(self, username, success): pass Added to UserManagerBad alongside its existing six methods. RUNNING THIS CHAPTER'S OWN CLASSIFIER ------------------------------ authenticate: {'auth'} create_user: {'auth'} export_report_to_csv: {'report'} generate_activity_report: {'report'} log_login_attempt: set() send_password_reset_email: {'email'} send_welcome_email: {'email'} total distinct concerns: {'email', 'auth', 'report'} ( 3 ) log_login_attempt classified as: set() log_login_attempt is classified as belonging to NO existing concern at all - not auth, not email, not report. It doesn't even register in the total-concerns count, which stayed at 3. WHAT THIS ACTUALLY REVEALS ------------------------------ This isn't evidence that log_login_attempt genuinely belongs to one of the three existing concerns - it's evidence that this chapter's own CONCERN_KEYWORDS dictionary is incomplete. The word "log" (or "audit", "security-log", etc.) was never added as a keyword for any concern, so the classifier is simply blind to this method, the same way it would be blind to any real method whose name happens to use vocabulary the classifier's own author never anticipated. WHERE THE NEW METHOD SHOULD ACTUALLY LIVE ------------------------------ Logging a login attempt is neither authentication logic itself (authenticate() decides whether a login succeeds; logging it is a separate concern - recording that a decision happened) nor reporting in this codebase's own existing sense (generate_activity_report and export_report_to_csv are user-facing/business reports, not a security audit trail). The honest conclusion is that this seventh method reveals a FOURTH, previously unaccounted-for concern - something like AuditLogger or SecurityLog - that this chapter's own three-way split (Authenticator, EmailService, ReportGenerator) didn't anticipate. Adding it to any of the three existing classes would just reproduce the exact mixed-concern problem this chapter's own Large Class finding already identified, one concern smaller. WHY THIS WORKS AS AN ANSWER ------------------------------ The classifier is run unmodified against a genuinely new method, its "no match" result is investigated rather than misread as "belongs to an existing concern," and the conclusion (this reveals a missing fourth concern, not a gap to force into an existing class) is reasoned from what the method actually does rather than from where the classifier happened to be silent.