Hacker Newsnew | past | comments | ask | show | jobs | submit | zabil's commentslogin

I have a slight dislike for JSON+REST for API's.

The design overhead involved in determining the correct URL and HTTP method adds a layer of subjectivity to the design and bike shedding arguments.

I’m not a huge fan of Protobuf/GRPC either, if there’s a better alternative I believe RPC is the right approach for exposing APIs.


I don’t think it’s bad on its own, but from my experience, the rollout can be messy and lock people out. Aadhaar in India had long registration queues, biometric issues, and banks making it mandatory. Even in the UK, the digital residency permit switch caused issues at border control.


It’s hard not to be overwhelmed by the Sagrada Família — it feels less like a building and more like a living organism stretching toward the sky. Makes Barcelona along all that it already offers a beautiful city to visit.

I also feel the tragedy behind its beauty. From what I've read, Gaudí dedicated later part of his life completely to it and he died poor and unrecognised, hit by a tram and mistaken for a beggar.


Not a fan of the new Safari design. I used to like it for its compact and minimalist look, but now the address bar and tab bar feel like they take up more space than they should.


In my experience, Page Objects sound neat in theory but end up as a leaky abstraction: they mix UI details with test logic, duplicate flows, and make even trivial UI changes ripple through dozens of files. What I’ve seen is indirection that hides test intent and bloats maintenance.

I also find them very developer-centric — testers get forced into upfront design work that doesn’t fit how they naturally test, and many struggle with it. I’ve had better results by expressing behavior directly and keeping UI concerns thin, instead of using a wrapper around page structure.


> In my experience, Page Objects sound neat in theory but end up as a leaky abstraction: they mix UI details with test logic, duplicate flows,

You might be asking too much of them to the point they become a burden.

1. Page Object Model should not contain any test-related stuff. It should abstract common page interactions:

  registerUser({ email: string, password: string, displayName: string })

  findProduct(name: string)

  addProductToCart(id: string, quantity: number)
etc

Then what you do in your tests is:

  registerUser("abc@foo.net", "passw0rd", "foo name")
  login("abc@foo.net", "passw0rd")'
  // now you test
  expect(page).findByText("Welcome back foo name").toBeVisible()
> and make even trivial UI changes ripple through dozens of files.

2. Given my previous example, if you changed the login or registration form you'd only update the implementation of `registerUser`.

In any case I also want to emphasize: POMs are very useful when collecting and reusing the data (e.g. in the previous example `login()` would take no params and reuse those declared before), you can achieve 95% of their functionality with plain simple helper functions.


I also find them very developer-centric — testers get forced into upfront design work that doesn’t fit how they naturally test, and many struggle with it. I’ve had better results by expressing behavior directly and keeping UI concerns thin, instead of using a wrapper around page structure.

I'm sorry, but if your testers are not comfortable getting involved in the early design stages of your software in a 21st century world, then there's at least a 90% chance that their primary role at your company is perpetuating organizational dysfunction.

Most of my career has been defined by cleaning up the gargantuan messes the culture of "throw tickets over the wall to QA" created, and it has been very, very ugly. It defies common sense how culture around tools and processes for dev and ops roles continues to evolve over time, but for some reason testers are still trying to test software off in a silo, like it's released once or twice a year on CD-ROM.


OP here. Ordinarily, I would agree with you, because PageObjects themselves are not composable, in languages belonging to the "Kingdom Of Nouns".

However, the following design, thanks to Clojure's language design, helped address a rather nasty situation.

A tightly scoped Domain Specific Language, over some Types of PageObjects, all of which compose arbitrarily (without breaking value semantics). So, if you wanted the `value` of a Modal box having all sorts of switches, form fields etc., you'd call `value` on it, and it would call `value` on all of its constituents, and return the immutable hash-map snapshot of whatever state it found.

  Cross-cutting concerns

  | v PageObject / DSL -> | open | close | open? | select | deselect | ... |
  |-----------------------+------+-------+-------+--------+----------+-----|
  | Dropdown              |      |       |       |        |          |     |
  | Checkbox              |      |       |       |        |          |     |
  | Switch                |      |       |       |        |          |     |
  | Modal                 |      |       |       |        |          |     |
  | SearchList            |      |       |       |        |          |     |
  | ...                   |      |       |       |        |          |     |
Concrete example (in the deck and demo linked below):

  (defprotocol IPageObject
    "Each PageObject MUST implement the IPageObject protocol."
    (page-object [this])
    (exists? [this])
    (visible? [this]))
And then an implementation like this:

  (defrecord Checkbox [target-css]
    IPageObject
    (page-object [this]
      this)
    (exists? [this]
      ;; webdriver check if target-css exists
      )
    (visible? [this]
      ;; webdriver check if target-css is visible
      )

    Selectable
    (select [this]
      ;; webdriver select the target
      )

    (deselect [this]
      ;; webdriver undo selection
      )
  
    (selected? [this]
      ;; webdriver return true if target selected
      )  

    Value
    (get-value [this]
      ;; webdriver return current selection state
      (selected? this)))
Deck: https://github.com/adityaathalye/slideware/blob/master/desig...

Talk + Demo: https://www.youtube.com/watch?v=hwoLON80ZzA&list=PLG4-zNACPC...

I also commented about it here: https://news.ycombinator.com/item?id=45161410 (Clojure's solution to the Expression problem).

That said, UI testing is a hot mess in general (especially for SPAs). I prefer to avoid automating anything but the "happy paths". IME, exploratory testing is better at sussing out corner cases, and "emergent" misbehaviours. So I do that, in addition to the "happy path" suites. Cue: James Bach et. al. https://www.satisfice.com/

Also I am warming up to server-generated HTML, because I can unit-test that, if I can use `hiccup` syntax + HTMX. In that case, I just make all request handlers spit out HTML fragments as Clojure data, and test those responses in my test suite.


Part of this is on developers. Refactoring is fine, but too often it turns into yak-shaving and nothing ships. The approach usually works: refactor in small steps and tie it to a feature so it’s testable and adds value.


Very much this. There's no need (and certainly never time) to add tests to the world or refactor everything. But it's often practical to figure out "I need to make changes "here" and add tests for that section and do whatever cleanup helps for that bit.


Does anybody have tips on how to invalidate a wallet address response if it's intercepted and modified like this?


Off the top of my head, you could include your own checksum in the payload. Their code only modifies the address. Nothing would prevent them from reverse engineering checksum, too.

There are ways to detect a replaced/proxied global window function too, and that's another arms race.


I’ve noticed that every time I open a browser to use the web version of an app, I get distracted and end up browsing unrelated stuff.

Switching to a standalone app helps me avoid that — fewer distractions, less wasted time. I’ve tried breaking the habit, but this is one reason I still prefer desktop version of the website.


do you have the same problem at the grocery store?


Surprisingly, no. I make a list know the aisles, pick stuff. But it’s not the same case on the web.


Used trunk-based dev a lot. Not a fan. It sounds good on paper, but in practice, it gets messy fast and code quality is hard to maintain, especially when teams are remote.

What actually works is trunk-based deployments — keep main always deployable, and ship from there. Simple.

PRs, are underrated. They’re great for sharing context. You get inline comments, CI runs, you can test stuff in isolation by spinning up infra, and teammates actually see what’s changing.

Stacked diffs make juggling multiple PRs manageable. And yeah, PR reviews can slow you down, but honestly, I think that's a plus. Slowing down just enough to have another human look at the code pays off more often than not.


I don’t understand why PRs are being discussed here at all – doesn’t anyone serious use trunk based development with code reviews? How is that different from a PR? Seems like we need to disentangle the discussion of whether code review is good from whether feature branches vs trunk based dev are good. Those are completely unrelated questions to me.

I think there are a lot of interesting questions about using feature flags (a baby branch) vs actual branches. Personally I’m pro flags and anti branches, after a lot of experience in developer tools and CI.


Definitely feature flags are the way to go. Having those code paths integrated early doesn't cost much and makes it basically free when you want to "merge" the feature into default.

This does require your software to have a decent architecture such that feature flags aren't littering every part of your codebase, though. Ideally you want something like a whole module/plugin being enabled/disabled right at the entrypoint of your program/module. But this also pays dividends in the long run.


There are different flavours of TBD. Some use short-lived feature branches, some commit directly to master. The article advocates for the latter.

PRs basically have a hard-requirement on branches (or equivalent, like fork), because the code that is being requested to pull needs to be available somewhere. The article also advocates for not using pull requests.

However people who take this position also often advocate for post-merge code review. And more advocate for pair programming or mob programming, which they consider to represent code review as well. So branchless TBD isn’t incompatible with code review, just code review as it is commonly practiced.


I'm pretty sure trunk-based development includes using feature branches and MRs/reviews etc. I didn't get the impression we were always supposed to commit directly to master (although that is possible for trivial things which reduces overhead).

Is everyone talking about the same thing here?


There are different flavours of TBD. Some use short-lived feature branches, some commit directly to master. See:

https://trunkbaseddevelopment.com/


If your team is very small then strictly creating feature branches and pressing the merge button immediately because there's nobody left to review it is silly. I like that it gracefully degenerates into just committing directly to the trunk when it makes sense.

This works with git (or DVCS in general) because your local "master" or whatever is a short lived branch. People seem to forget but with git you are branching every time you clone. Obviously committing broken stuff and WIPs directly to the trunk isn't going to work.


One thing I really appreciated during the peak years of working with XSLT was how much I learned about XPath. Once it clicks, it’s surprisingly intuitive and powerful. I don’t use XSLT much these days, but I still find myself using XPath occasionally. It’s one of those tools—once you understand it, it sticks with you.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: