schmonz.com is a Fediverse instance that uses the ActivityPub protocol. In other words, users at this host can communicate with people that use software like Mastodon, Pleroma, Friendica, etc. all around the world.

This server runs the snac software and there is no automatic sign-up process.

Search results for tag #refactoring

#refactoring boosted

[?]hackaday » 🤖 🌐
@hackaday@www.urbanmind.net

Do not extract file helpers from a messy module yet. Snapshot every resolved absolute path before the first edit. Relative opens form a hidden contract across three roots.

Most failed extracts start as a path-root mismatch. The helper looks cleaner after the extract lands. The files then land in a different directory tree.

Three roots, one unpublished API


A typical messy module mixes three path roots. None of them appear in the public function signature.

os.getcwd() follows the process, not the source file. Pytest, systemd, and cron each change that value.

Path(__file__).resolve() follows the module on disk. A later package move silently retargets every relative open.

An env var such as DATA_DIR may override both. Empty, relative, and absolute values all behave differently.

The public function still accepts only a basename. Callers believe the output path stays stable. That belief does not survive a chdir.

Teaching example: three writes, three roots


The listing below is a teaching example, not production code. It writes one report beside three different roots.

# report_kit.py — messy on purpose
from __future__ import annotations

import json
import os
from pathlib import Path

HERE = Path(__file__).resolve().parent

def write_daily_report(name: str) -> dict[str, str]:
data_dir = os.environ.get("DATA_DIR", "data")
cwd_out = Path("out") / name
here_out = HERE / "out" / name
env_out = Path(data_dir) / name

payload = {"name": name, "pid": os.getpid()}
text = json.dumps(payload, sort_keys=True) + "\n"

cwd_out.parent.mkdir(parents=True, exist_ok=True)
here_out.parent.mkdir(parents=True, exist_ok=True)
env_out.parent.mkdir(parents=True, exist_ok=True)

cwd_out.write_text(text, encoding="utf-8")
here_out.write_text(text, encoding="utf-8")
env_out.write_text(text, encoding="utf-8")

return {
"cwd": str(cwd_out),
"here": str(here_out),
"env": str(env_out),
}

A naive extract wraps the three write_text calls. It often introduces Path.cwd() in one place. One root then silently absorbs the other two.

Return values still look like relative strings. Tests that assert those strings stay green. The bytes move anyway.

Artifact: a path ledger


Build a ledger before any helper extract. Record caller, raw argument, and resolved absolute path. Hash the sorted ledger. Treat that hash as a characterization oracle.

# path_ledger.py — teaching harness
from __future__ import annotations

import hashlib
import json
import os
import traceback
from pathlib import Path

LEDGER: list[dict[str, str]] =

[]def _caller() -> str:
frames = traceback.extract_stack()
for frame in reversed(frames[:-1]):
if "path_ledger.py" not in frame.filename:
return f"{frame.filename}:{frame.lineno}:{frame.name}"
return "unknown"

def record(kind: str, raw: str, resolved: Path) -> None:
LEDGER.append(
{
"kind": kind,
"caller": _caller(),
"raw": raw,
"cwd": os.getcwd(),
"resolved": str(resolved.resolve()),
}
)

def ledger_hash() -> str:
blob = json.dumps(LEDGER, sort_keys=True, indent=2)
return hashlib.sha256(blob.encode("utf-8")).hexdigest()

def dump(path: Path) -> str:
path.write_text(
json.dumps(LEDGER, indent=2, sort_keys=True) + "\n",
encoding="utf-8",
)
return ledger_hash()

Wrap writes at the test boundary only. Do not patch production code for this measurement. Run the same invocation the module already trusts.

# test_path_ledger.py — characterization, not a unit test
from __future__ import annotations

from pathlib import Path
from unittest.mock import patch

import path_ledger
import report_kit

GOLDEN = Path(__file__).parent / "goldens" / "report_kit_paths.json"
GOLDEN_HASH = Path(__file__).parent / "goldens" / "report_kit_paths.sha256"

def _traced_write_text(self: Path, *args, **kwargs):
path_ledger.record("Path.write_text", str(self), self)
return Path.write_text(self, *args, **kwargs)

def test_write_daily_report_path_ledger(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
monkeypatch.setenv("DATA_DIR", str(tmp_path / "env-data"))
monkeypatch.setattr(report_kit, "HERE", tmp_path / "pkg")
(tmp_path / "pkg").mkdir()

with patch.object(Path, "write_text", _traced_write_text):
report_kit.write_daily_report("daily.json")

digest = path_ledger.dump(tmp_path / "ledger.json")
if not GOLDEN.exists():
GOLDEN.parent.mkdir(parents=True, exist_ok=True)
GOLDEN.write_text(
(tmp_path / "ledger.json").read_text(encoding="utf-8"),
encoding="utf-8",
)
GOLDEN_HASH.write_text(digest + "\n", encoding="utf-8")
raise AssertionError("golden created; rerun to pin")

assert digest == GOLDEN_HASH.read_text(encoding="utf-8").strip()

Label this pin as an oracle, not as coverage. The first run writes goldens on purpose. The second run fails on any resolved-path drift.

Trace mkdir in the same harness when directories matter. A helper can reuse a folder the original code created. That reuse still retargets later writes.

Decision table for one extract


Use the table before any patch is accepted. Each row is a veto, not a preference.

Signal in the ledger

Safe extract?

Required pin

cwd-relative out/name

Not yet

chdir plus expected absolute

__file__-relative out/name

Not yet

frozen HERE

env-relative DATA_DIR/name

Not yet

empty, relative, absolute env

mixed roots in one function

No

split by root, not call shape

only basenames change

Yes

hash still matches


A model often groups the three writes together. They share write_text, so the grouping looks obvious. The ledger groups them by root instead.

Root grouping is the correct split. Call-shape grouping is the usual defect.

Numbered workflow


Follow these steps in order and skip none.

  1. Record one real invocation with cwd, env, and argv stored together.
  2. Trace every open, write_text, mkdir, and Path constructor you might move.
  3. Resolve each raw path against the recorded cwd, storing absolutes only.
  4. Hash the sorted ledger, then commit both the hash and JSON.
  5. Add three extra invocations: new cwd, unset DATA_DIR, absolute DATA_DIR.
  6. Refuse every extract until all four hashes stay stable across reruns.
  7. Extract one root only, and keep the other two writes inline.
  8. Diff the ledger JSON, not the source, before any merge.

Relative goldens will lie after a machine change. Absolute goldens survive a different checkout path. That is the entire point of the pin.

Commands for the first pin:

mkdir -p goldens
python -m pytest test_path_ledger.py -q
# first run creates goldens and fails
python -m pytest test_path_ledger.py -q
# second run must pass before any extract

Commands after a proposed extract:

python -m pytest test_path_ledger.py -q
git diff -- goldens/report_kit_paths.json
# any resolved-path line change is a rejected patch

A smoking-gun diff looks like this fragment:

- "resolved": "/tmp/pytest-of-dev/test0/out/daily.json"
+ "resolved": "/home/ci/project/out/daily.json"

The source diff can still look like a tidy helper. The ledger line is the reject signal.

Smallest safe change


The smallest change moves one root. It does not introduce a generic writer yet.

def _write_cwd_report(name: str, payload: str) -> str:
target = Path("out") / name
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(payload, encoding="utf-8")
return str(target)

Leave __file__ and DATA_DIR writes in the original function. A later extract can take the second root. Each extract must keep the ledger hash unchanged.

Do not normalize paths inside the new helper. Normalization is a behavior change, not cleanup. Record it as a new ledger when you truly need it.

Avoid .resolve() in the extracted helper. resolve() follows symlinks and can rewrite goldens. Prefer the same construction the messy module already used.

Mixed open() and Path modules


Some messy modules still call open() directly. Trace that path with a thin wrapper. Keep the same ledger schema for both styles.

import builtins
from pathlib import Path

_real_open = builtins.open

def traced_open(file, mode="r", *args, **kwargs):
raw = str(file)
path_ledger.record("open", raw, Path(file))
return _real_open(file, mode, *args, **kwargs)

Install the wrapper only inside the characterization test. Production code should keep its original open. The oracle lives in the test process.

If both open and Path.write_text appear, keep both kinds. Dropping one kind hides a root. Hidden roots are how extracts ship broken CI writes.

Where a free model fits


A free coding model can draft the one-root helper. It cannot choose the root. The ledger already chose.

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

MonkeyCode provides free model access and a free server option. Use the server to run the four pinned invocations. Feed the model the messy function, the ledger JSON, and the decision table. Reject any patch that alters a resolved field.

The model is a diff generator in this workflow. The hash remains the reviewer for every patch. Do not skip that reviewer for a cleaner diff.

Failure analysis


Hash changes but the source looks equivalent. A Path constructor started calling .resolve() early. Absolute strings then diverge on symlinks.

Hash stays stable on a laptop and fails in CI. The golden cwd was never isolated. Rerun the pin under tmp_path.

Only two of three writes appear in the ledger. mkdir created a directory the extract later reuses. Trace mkdir as a first-class event.

Env values look absolute in every golden row. The test set an absolute DATA_DIR only. Add the unset and relative cases before review.

Returned relative strings still match after the extract. Callers never saw the absolute target. Assert the ledger, not the return map.

Limitations


This ledger does not prove functional correctness of the report. File contents can still rot under this pin. Pair it with a payload hash when bytes matter.

It misses networked I/O by design. HTTP and object-store clients need a different oracle. Do not reuse this hash for those calls.

It is weak against symlink farms in deploy trees. resolve() follows links; absolute() does not. Pick one rule and keep it fixed.

Race conditions remain outside the ledger. Two processes can share one cwd. The ledger is per-process and will not serialize them.

Windows drive letters and UNC paths need extra goldens. Do not copy a POSIX hash onto Windows runners. Split those hashes by platform.

Who should not use this


Do not use this workflow on a greenfield module. Write explicit path arguments first in new code. There is nothing useful to characterize there.

Do not use it when output locations must change on purpose. Update the golden in the same commit as the move. Do not treat the hash as sacred then.

Do not use it as a substitute for backup policy. Characterization does not recover overwritten files. Keep real backups for destructive jobs.

Skip it for one-off notebooks and scratch CLIs. The process cwd is the product in those tools. A ledger mostly adds noise there.

Checklist before merge


  1. Four invocations produced four hashes, and all four stayed green.
  2. One root was extracted, and two roots remained inline.
  3. The ledger JSON diff is empty after the helper lands.
  4. The helper introduced no new .resolve() calls on write paths.
  5. DATA_DIR cases include unset, relative, and absolute values.

If any box is still open, keep the helper on the branch. Ship the path pin first. The extract can wait for a green hash.

Run the ledger on a free server if you already have one. Keep the extract behind that green hash.
Characterize Path Resolution Before You Move One open()

    [?]Rafael Pérez 🍁 » 🌐
    @rperezrosario@mastodon.social

    River Engineering writer Vivian Mathews retells their company's 16-month-long saga to replace an aging accounting ledger system with a refactored, highly optimized new version. They go through the nitty-gritty of how they successfully pulled-off a zero-downtime migration including code examples and key takeaways for the TL;DR crowd.

    "We replaced our ledger with two functions"

    river.com/content/we-replaced-

    A detailed black-and-white line-art scene contrasts a tangled, aging ledger system with a clean modern code system, connected by a bridge representing a careful zero-downtime migration. Image designed and executed by GPT-5.6 Luna.

    Alt...A detailed black-and-white line-art scene contrasts a tangled, aging ledger system with a clean modern code system, connected by a bridge representing a careful zero-downtime migration. Image designed and executed by GPT-5.6 Luna.

      #refactoring boosted

      [?]ainews » 🌐
      @sayzard@mastodon.sayzard.org

      Vaibhav (VB) Srivastav (@reach_vb)

      Codex의 실험적 기능으로 컨텍스트 윈도우를 넘어서 노트를 유지하고, 이전 메시지·도구 출력(노트에 누락된 세부 정보 포함)을 검색할 수 있게 됐다고 안내했다. 장시간 디버깅과 대규모 리팩터링에서 컨텍스트 손실을 줄이는 데 유용하며, Codex 업데이트 후 Astra를 선택해 사용할 수 있다.

      x.com/reach_vb/status/20966578

        #refactoring boosted

        [?]Frontend Dogma » 🤖 🌐
        @frontenddogma@mas.to

        We Let AI Agents Rewrite a 92M-Message-a-Day Service in Go—Zero Incidents, by (not on Mastodon or Bluesky):

        checklyhq.com/blog/agentic-rew

          #agile boosted

          [?]Richard Griffiths » 🌐
          @dectentoo@mastodon.ie

          The best refactoring doesn't necessarily produce the cleverest code.

          It produces better code.

          Those aren't always the same thing.

          A new abstraction might reduce duplication while making the system harder to understand.

          A design pattern might look elegant while adding machinery nobody needs.

          A shorter solution might become cryptic.

          Technical excellence requires judgement.

          Not commandments.

            #refactoring boosted

            [?]hackaday » 🤖 🌐
            @hackaday@www.urbanmind.net

            Rust is an increasingly popular COBOL migration target for organisations that want both memory safety...
            COBOL to Rust Migration - A UK Enterprise Guide 2026

              #refactoring boosted

              [?]ainews » 🌐
              @sayzard@mastodon.sayzard.org

              BOOTOSHI (@KingBootoshi)

              AI 코딩 에이전트에 리팩터링 시 기존 코드를 방치하지 말고 삭제·정리하도록 유도하기 위해, '탈피하는 거미처럼' 같은 비유적 프롬프트를 사용한다는 경험 공유다. 에이전트의 코드 정리 행동을 유도하는 프롬프트 설계 사례지만, 효과는 개인적 관찰 수준이다.

              x.com/KingBootoshi/status/2088

                #refactoring boosted

                [?]Hacker News » 🤖 🌐
                @h4ckernews@mastodon.social

                #refactoring boosted

                [?]Leanpub » 🌐
                @leanpub@mastodon.social

                A Short Guide to Naming by Tim Ottinger is free with a Leanpub Reader membership! Or you can buy it for $6.50! leanpub.com/naming_shortguide

                  #refactoring boosted

                  [?]Habr » 🤖 🌐
                  @habr@zhub.link

                  [Перевод] Экономическая выгода рефакторинга в эпоху AI-агентов

                  Осваивая разработку с помощью AI-агентов, я написал веб-приложение для собственной ежедневной работы. Проект получился довольно сложным: с динамическим обновлением интерфейса и поиском, модальными окнами, автосохранением, интеграциями с внешними системами, модулями машинного обучения, текстовым анализом, фоновыми задачами и автоматическим деплоем. Объём кода составил около 150 000 строк, из которых примерно 120 000 написаны на Rust, а остальные - на TypeScript и Terraform. Весь этот код сгенерировали агенты - в основном Claude Code и частично Cursor . За редкими исключениями я почти не открывал и не читал исходные файлы. В процессе разработки я начал замечать странности. Когда в терминале мелькнула правка 4000-й строки в одном файле, я решил посмотреть на код ближе. Выяснилось, что слой доступа к данным разросся до 6000 строк. С каждой новой функцией он продолжал расти. В коде каждого запроса, чтения или записи повторялись настройка HTTP-запроса, кодирование и декодирование JSON. В итоге весь слой доступа к данным оказался в одном файле на 17 155 строк Rust.

                  habr.com/ru/articles/1065178/

                  #refactoring boosted

                  [?]Frontend Dogma » 🤖 🌐
                  @frontenddogma@mas.to

                  #refactoring boosted

                  [?]N-gated Hacker News » 🤖 🌐
                  @ngate@mastodon.social

                  👔💼 Behold, the masterpiece where buzzwords go to die, as our corporate sage Giles Edwards unravels the economic enigma of with the depth of a shallow puddle. 🌊🔧 Prepare to be dazzled by the revelation that cleaning up code is good for business—who knew? 🤯💸
                  martinfowler.com/articles/expl

                    #refactoring boosted

                    [?]Hacker News » 🤖 🌐
                    @h4ckernews@mastodon.social

                    #refactoring boosted

                    [?]ainews » 🌐
                    @sayzard@mastodon.sayzard.org

                    Alper Tunga (@altudev)

                    Cursor의 Fable Extra High 모드가 대규모 리팩터링 작업에서 6개의 탐색 에이전트를 병렬로 생성하는 사례를 공유했다. 멀티 에이전트 기반 코드 탐색·리팩터링 워크플로의 발전을 보여주지만, Codex·Claude 대비 사용량 리셋 정책은 아직 부족하다는 평가다.

                    x.com/altudev/status/208169828

                      #refactoring boosted

                      [?]ainews » 🌐
                      @sayzard@mastodon.sayzard.org

                      0xMarioNawfal (@RoundtableSpace)

                      Codex Code Rot Cleaner가 애플리케이션 코드베이스에서 안전하게 제거 가능한 죽은 코드(dead code)를 탐지한다고 소개했다. 코드 생성 에이전트와 정적 분석을 결합해 레거시 코드 정리, 유지보수 비용 감소, 리팩터링 검토 자동화에 활용할 수 있는 개발 도구 사례다.

                      x.com/RoundtableSpace/status/2

                        #refactoring boosted

                        [?]Su_G » 🌐
                        @Su_G@aus.social

                        RE: aus.social/@andyjennings/11688

                        Ha ha. Slopfix says it is:
                        “getting paid according to how much code it deletes. Its three engineers agree to a line-reduction target before starting, with a stated example of whittling a 100,000-line project down to 35,000 while maintaining the same functionality. The best part? Slopfix uses AI coding agents itself to do the trimming.” but describes them as being kept on “a very short leash”.

                        Interesting read & approach, was wondering when someone would do this…

                          #refactoring boosted

                          [?]Jason Yip » 🌐
                          @jchyip@mastodon.online

                          #refactoring boosted

                          [?]Frontend Dogma » 🤖 🌐
                          @frontenddogma@mas.to

                          Back to top - More...