HN user

jpatte

214 karma

Software engineer Co-founder/CTO/Architect/Lead dev of https://www.featuremap.co github.com/jpatte

Posts2
Comments123
View on HN

It doesn't make much sense for people who always heard and thought that "an interface just lists the public methods and properties of a class". In that view the classes always come first and the interfaces are unnecessary boilerplate.

However if instead you assume that "a class is just an implementation of an interface", then everything changes. Now the interfaces come first and classes are required to materialize them. In that paradigm objects only communicate with interfaces, never (or almost never) with other classes unless a specific implementation is required. Which is why an interface is always defined for a class even if there is no plan for other implementations of it.

Rather than a "contract", think of an interface as the description of a job. If you ever need to write a safety procedure, does it make more sense to write "In case of fire, call John; John happens to know how to extinguish a fire." or "In case of fire, call a fireman."? "Fireman" is an interface. "John" is a class implementing that job. It might be the only class in the codebase that implements it, but that is no concern of the caller. They just want that fire dealt with.

I discovered software programming about 20 years ago during high school by fooling around with my Casio programmable calculator. I spent countless hours writing small utility programs and games in BASIC, then I bought a more powerful calculator (still Casio though) which allowed me to learn and write programs in C, ASM (286) and C++.

Around 2005 I got myself a Casio ClassPad 300, which was like a strange combo of a calculator and a PDA. It had a big B&W touchscreen with a stylus. It was the first Casio handheld that came with an official SDK to build native apps for the device; before that it was only possible through pure reverse engineering and hacking -- good times. :) So there were 2 options to write programs for this device: you could either code in BASIC directly on screen, which was easy but very limited and suffered terrible performance -- or you could use a computer to write and compile a C++ add-on and then transfer it to the device, which was extremely powerful but of course a lot more complicated especially for beginners.

So here is what I did: I took the C code of the Lua 5.1 interpreter, embedded it into a new C++ add-on, and then I made it possible to write and execute Lua code directly on the device through this add-on. I even made a new custom font for the text editor and a new virtual keyboard for the stylus to maximize the amount of code visible on screen. I wrote my own memory block allocator for the interpreter to provide access to additional RAM space, among many other hacks. But more importantly I made most of the features of the SDK accessible from Lua scripts, which means it was then possible to write or read persistent files, draw any kind of figures on screen, create user interfaces using native UI components, use advanced math features, send data packets through USB etc.

The project quickly got a lot of interest inside our small community: now you had a third option for coding, offering excellent performance, lots of advanced features and it was very easy to start with. It was the first time I built a tool incrementally based on user feedback instead of building it just for me. Even the maintainers of the SDK and official apps followed the project closely. Eventually I moved on and never got the chance to actually implement everything I had in mind. I learned a lot, had lots of fun, and this experience has been key to the identification of my ideal career path.

Let's say my startup makes a product featuring some sort of kanban-like board. The user moves a card from one column to the other. According to this article, the frontend might just need to perform an UPDATE on the right table from the database and that would be it.

Yet, this is what my backend does:

* make sure the user is allowed to move that particular card.

* update the database.

* add an entry to the board's activity log.

* notify all connected clients listening to events from this board that a change occurred, so they can refresh the UI instantly.

* if some users asked to be notified about changes, generate notifications.

* if some of these users are offline but still want to be alerted, generate and queue some emails to send.

* add an entry in a raw text log for easy debugging.

* register the event in some kind of analytics storage for future stats.

* if the board is integrated with e.g. Slack, call Slack's API.

* if some users registered webhooks through my API, trigger those.

I'm so glad my frontend engineers actually do not have to worry about how to do any of that.

Edit: format

After reading the article I'm not entirely sure all these drivers did participate in the race using their own setups while staying home. Especially after this part: "[Pike] and Majors tried to fill up a field that reflected this big tent, letting in fellow NASCAR crew members, as well as some public relations and social media specialists."

Can someone please tell me they did not turn a strong recommendation to avoid public events (which lead to the competition being cancelled) into an opportunity to gather tens of people at one place?

FYI my wife and I signed for a mortgage 4 months ago here in France for our new home. 325k€, 25-year, 1.66% interest rate, 0.8% insurance rate for complete coverage of the both of us. Both fixed rates.

The rates were actually going up at that time - if we could have borrowed 6 months earlier we would likely have had even better rates. Also if you can borrow for a shorter period of time the rates get much lower.

You seem to forget that maths and physics are meant to describe reality, not be reality. Any abstract concept (like numbers, forces, shapes, temperatures, energy levels, ...) we use to describe a real thing is different from that thing itself. If you think about it, even 2 isn't "more real" that Pi, because there are no 2 identical things in reality.

When we say "a human hand has 5 fingers", we use the abstract concept of "finger" to make that description. It is abstract because each "finger" is actually unique. It's just a handy approximation we use (pun intended) for descriptive goals.

Basic maths is not reality. Therefore no, irrational numbers do not "fall out of it".

Edit: format

Knowing how to sell/market your product is more important than having a fully functional or carefully engineered product. Nobody will give you money for your (master)piece of software if they don't know what it does or what it's for. Sounds trivial, and yet the better you are at software development, the harder it is to keep in mind.

Just because you are good at something doesn't mean you should be focusing on that thing and leave the rest for later.

Something important to keep in mind for founders and investors I haven't seen mentioned yet: in France, capital gains are taxed at 33%. And there is an additional tax for wealthy people (ISF, impôt sur la fortune) to pay each year.

If you want to be a millionaire in France, get ready to pay hundreds of thousands of euros in taxes.

For those wondering (spoilers), the puzzle he's talking about in section 2 ("the second puzzle in the game") is a simple puzzle where you just have to double the values provided as input to produce an output. The naive solution at 240 points he mentions is extremely straightforward:

  mov p0 acc  # place input value into internal register
  mul 2       # multiply register by 2
  mov acc p1  # place register value into output
  slp 1       # sleep 1 cycle, wait for next input
The only way (I can think of) to optimize this is by cheating, i.e. by writing an algorithm specifically fitted for the kind of input we have to deal with. Looking at the input, we see that for example there are only 3 input values (0, 25 and 50) and there seems to be more zeros than other values. Based on this info we can try to predict what value is likely to show up as input and follow a dedicated path to handle it, in order to be as efficient as possible.

I must admit I was happy with the 240 solution and never thought there was a better way until I read this article. Now I feel obliged to at least go down to 156 :D

I think the author missed the opportunity to show how choosing better identifiers for his example would have eliminated the need for comments immediately. Also notice how his comments were actually bad from the beginning: it said the method returns something even though it doesn't.

Example:

  def printPlayerLineup(playerPositionByNames)
    batOrder = 1
    playerPositionByNames.each do |name, position|
      puts "#[name} bats #{batOrder} and plays #{position}"
  	batOrder += 1
    end
  end
There are also a few tips to give about how to pick good names. For example if you expect an array of player names the argument should be called `playerNames`, not `players`. Another example is function names should always start with a verb.

Also, if you end up writing comments just to specify types, consider using a statically typed language instead.

I don't know what you call a "very large" app, but I have a fairly complex app relying solely on Knockout with hundreds of observables/computeds being triggered in real-time to update the state of the UI as users drag and drop visual elements and it works like a charm. The UI is never out of sync with the model. I'm using Knockout 3.0, maybe things improved since you wrote your app?

Here [1] is the second part of the presentation, featuring the complete video (which you can find here [2]). I actually think the way they presented the device during the keynote was brilliant: present it first as a "regular" laptop, then revisit the presentation immediately and reveal the device as what it actually is (a tablet pc with a base). Even if you could rather easily see it coming, I think a lot of minds were blown at that moment.

[1] https://www.youtube.com/watch?v=2UAvdxEjns0

[2] https://www.youtube.com/watch?v=XVfOe5mFbAE (1.6M views in about 22 hours)

The solution presented here basically consists of implementing a VehicleType class with a bunch of static instances without using the class syntax. I can't decide if this was a deliberate decision from the author or if he just didn't realize this.

Wait, how does that work? Looking at the malicious javascript code issuing ajax requests to github, it doen't seem github's response is evaluated. Is this alert even displayed?

If that is the case, why not do something even more radical in the response like changing the targeted urls ? They could replace them by baidu urls for example, effectively transforming a DDoS against github into a DDoS against baidu (not saying baidu is the author of the attack here, but that would certainly have an impact on the traffic being monitored by the GFW).

It's not about what people believed in the past or what they believe now, it's about what they might believe in the future.

By erasing all traces of other religions (and even all traces of other philosophical trends), they essentially make their god "The One And Only God". How could future generations believe in anything else than Allah's almighty existence when apparently everything men did or do is about Him?

They are reshaping History in order to shape the future.

There is no missing foreach loop because LINQ iterators are smart enough to combine predicates whenever possible (source here: http://referencesource.microsoft.com/#System.Core/System/Lin..., see line 204 when dealing with arrays).

You're right it's missing the actual function calls, but that wasn't the point: the point here was that LINQ avoids building temporary enumerations and iterating over them like JS functions do.

LINQ IEnumerable functions are implemented using the `yield return` operator:

  public static IEnumerable<T> Where<T>(IEnumerable<T> source, 
                                        Predicate<T> predicate)
  {
    foreach(var item in source)
    {
      if(predicate(item))
        yield return item;
    }
  }
which means
  var results = myList
    .Where(x => x.name == 'Person');
    .Where(x => x.age > 18);
    .ToList();
is executed just like
  var results = new List<Foo>();
  foreach(var x in myList)
  {
    if(x.name == 'Person')
    {
      if(x.age > 18)
        results.Add(x);
    }
  }

This is great! Being able to save my favorite combos and set an "off" timer is nice, now would it be possible to set a timer to automatically switch to another (random or specific) combo? I'd light to define day/night cycles or sun/rain cycles :)

Also, once you saved a combo, how do you edit it? It seems there is no way to get back to the home page once a fav combo is started.

The concept of commands is very useful but I don't think it belongs to the event sourcing pattern. Event sourcing is just a way to write and read data, it doesn't say anything about how you process inputs and how that processing can lead to a change of data. For that concern there exist other patterns like CQRS which introduces the concept of command. These patterns are complementary, and using both CQRS + ES is actually common practice.

I'm currently in the process of redesigning the whole server architecture of our SaaS application to embrace event sourcing - we were using a classic relational database until now. I'm excited by all the new possibilities this will give us, but it's a lot of work to rewrite just about everything and to migrate old data into event streams. My advice to anyone who considers event sourcing for future projects: use it from the beginning. Transitioning from a more traditional model is hard.

Btw, the author seems to make a confusion between events and commands. These are not the same thing: a command represents an action (by the user, an other system or an internal process), while an event represents a change in the data. A command may generate 1 or several events during its processing. It is not saved in a data store, but it can be replayed in case of failure if retry policies are in place.